How can you cancel a SQL Server execution process programmatically - sql

Let's say you have execute the following (long running) process from your code:
int processID = DB.Execute(SQL); //some long running sql statement
Is there a way to programatically call SQL Server to cancel the process if it is taking too long (kind of like hitting the "Stop" button in QueryAnalyzer)?
//cancel the process if it is taking too long
DB.Execute("sp_CancelProcess #ProcessID=" + processID);

use KILL with the process id:
KILL 53;
Just be aware that you can't kill your own spid, you need to create another connection and then kill the spid from the
if you try to kill your own SPID you will get the following error
Server: Msg 6104, Level 16, State 1, Line 1
Cannot use KILL to kill your own process.

Kill #Spid
note that this is a last effort. you should just close the connection on the client to kill the process.

sp_who2
List of process displays
Find you SPID
Kill SPID
If error message you can't kill your own process
See where the process rund in your management studio and stop it.
Or close current connection and reopen and try to kill now.

You have to run your query asynchronously, as follows:
SqlConnection _anotherConnection;
SqlCommand _anotherCommand;
IAsyncResult _anotherCommandStarted;
_anotherCommand = _anotherConnection.CreateCommand();
_anotherCommand.CommandText = string.Format("SET DEADLOCK_PRIORITY HIGH; BEGIN TRANSACTION; {0};", hookCommand);
_anotherCommand.CommandType = CommandType.Text;
_anotherCommand.ExecuteNonQuery();
_anotherCommand.CommandText = "UPDATE Data.Hook1 SET i=1-i";
_anotherCommandStarted = _anotherCommand.BeginExecuteNonQuery();
To cancel the command, run this:
_anotherCommand.EndExecuteNonQuery(_anotherCommandStarted);

Related

Understanding SQL Server kill statement [for non-admin user]

I am looking into how a database management system performs a "cancel" operation when the cancel button is hit on the query. While it doesn't show what query it runs when it does cancel, here is what it shows in the logs:
2019/01/03 22:09:16:433 MSSQL cancelCurrentQuery failed via spid (54). Error: Msg 6102, Level 14, State 2.
User does not have permission to use the KILL statement.
2019/01/03 22:09:16:433 MSSQL cancelCurrentQuery is going to try via dbcancel.
2019/01/03 22:09:16:533 Cancelling current query (finished).
I assume KILL is trying to do KILL {sid} and it fails to do that because of permissions and then calls back to dbcancal. What is dbcancel? And what would be an example of that from the command line?
Additionally, how is it possible for me to kill the queries that I've issued if I cannot use the kill command?
Msg 6102, Level 14, State 2.
User does not have permission to use the KILL statement. (Line 1)

sql: set connection timeout in the connection string

In a console app I have a connection string like this:
Data Source=localhost;Initial Catalog=database_name;Integrated Security=True;Connect Timeout=100
I've read here that I need to add Connect Timeout to the connection string to set the timeout, but if I run a query that contains
WAITFOR DELAY '00:00:40';
I'll get a timeout exception, so it seems that the timeoput from the connection string is ignored. so how to set the timeout in the connection string (and not on the connection or command objects)?
There are two timeouts relating to SQL connections/commands - there is a connection timeout, that affects how long a connection is willing to wait when you try to open it, and a command timeout that affects how long an individual command being executed will wait.
You need to adjust the second of these - by e.g. setting the CommandTimeout property on the SqlCommand object.
It's not ignored, that's the behavior...if it times out, it throws an exception. If it didn't timeout, it would just run until the query returned.
Just use a try-catch block and do what you want when the exception is thrown.

Will the state of the transaction remain even if I open and close connections to the database

I have a "private" method that executes an sql instruction on my sqlite database:
-(void)runQuery:(const char*)query isQueryExecutable:(BOOL)queryExecutable withArguments:(NSArray*)arguments
The problem is that at the beginning of the method, it opens a connection to the database and finally at the end of the methods it closes it.
Now, what I want is to create 3 private methods for creating, committing and rolling back a transaction, that each will call
sqlite3_exec(db, %command%, 0, 0, 0)
where %command% is "BEGIN", "COMMIT", "ROLLBACK", depending on the method.
And, what I want to do next is call begin transaction and afterward use the runQuery:isQueryExecutable:witArguments: method described earlier, and finally commit or rollback.
My question is: will the transaction remain open, even though each time I call runQuery:isQueryExecutable:witArguments: I open and close a connection to the database ?
Sample code:
createTransaction
for n times:
call runQuery
commitTransaction
Every connection uses exactly one transaction; closing a connection with a still-active transaction will roll it back.
You should not re-open the database repeatedly. Just use a single connection for all your database accesses.

Control the timeout for locking Exclusive SQLite3 database

I have a SQLite database that I want to lock for synchronization purposes. I don't want a process that runs async on a different box processing data that has been added from a different box until it has finished with updates. DataAccess is a class that connects to sPackageFileName and reuses the same connection as long as sPackageFileName is the same or unless .Close method is called. So basically DataAccess.ExecCommand executes a command.
In Google I found this ....
DataAccess.ExecCommand("PRAGMA locking_mode = EXCLUSIVE", sPackageFileName)
DataAccess.ExecCommand("BEGIN EXCLUSIVE", sPackageFileName)
DataAccess.ExecCommand("COMMIT", sPackageFileName)
This works as advertise. If I run this on box A and then on box B I get a "database locked" exception. The problem is how long it takes. I found a PRAGMA busy_timeout. This PRAGMA is timeout controls access locks, not database locks. I am stratring to think there is not PRAGMA for database lock timeout. Right now it seems about 3-4 minutes. One other note, the sPackageFileName is not on either box, they (box A and B) connect to it over a share drive.
Also I am using the VB.NET wrapper for the SQLite dll.
CL got me on the right trail. It was the timeout of the .NET command. Here the code setting it up from my class.
Dim con As DbConnection = OpenDb(DatabaseName, StoreNumber, ShareExclusive, ExtType)
Dim cmd As DbCommand = con.CreateCommand()
If _QueryTimeOut > -1 Then cmd.CommandTimeout = _QueryTimeOut
Don't get hang up on the variables, the purpose of posting the code is show I could show the property I was talking about. The default _QueryTimeOut was set the 300 (seconds). I set cmd.ComandTimeout to 1 (second) and it returned as expected.
As CL finally got through to me, the timeout was happening someplace else. Sometimes it takes a kick to get you out of the box. :-)

SQL bcp The semaphore timeout period has expired

I'm making a bulk copy onto a file of a select in my database.
DECLARE #cmd varchar(1000)
DECLARE #sql varchar(8000)
SET #cmd='"select * from [MyDB].[dbo].MyTable"'
SELECT #sql = 'bcp '+#cmd+' queryout C:\myfile.txt -c -t -T -S MyServer -U user -P password';
exec xp_cmdshell #sql;
If I change the parameters and I execute the same command on the database test on my machine it works, but on the database server I get this error:
Msg 121, Level 20, State 0, Line 0
A transport-level error has occurred when receiving results from the server. (provider: TCP Provider, error: 0 - The semaphore timeout period has expired.)
I check server name, user, password, table name and they are correct, so I cannot understand what I'm doing wrong.
Can someone help me with this issue?
thanks
Increase timeout seconds in connection string.
private static void OpenSqlConnection() {
string connectionString = GetConnectionString();
using(SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
Console.WriteLine("State: {0}", connection.State);
Console.WriteLine("ConnectionTimeout: {0}",
connection.ConnectionTimeout);
}
}
static private string GetConnectionString() {
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file, using the
// System.Configuration.ConfigurationSettings.AppSettings property
return "Data Source=(local);Initial Catalog=AdventureWorks;" + "Integrated Security=SSPI;Connection Timeout=30";
}
I had the same error. A third-party tool was connecting to the database to extract data for import into a business intelligence system. Each extract/import would run for about 1 hour and there would be something like 10 to 15 separate queries in the process. Fortunately we had logging in place - so we knew at what time each of those queries was starting and ending. The extract/import process was saying that it was completing successfully after 30 minutes - rather than taking about 1 hour. I was able to isolate the query during which the process was failing. When I ran that query in SSMS I got the same error you've given in the question.
However, when I ran that query in another environment, I got an error that a subquery cannot return more than one row.
Sure enough, when I commented out my subqueries in the prod environment, the query ran without any error.
So ultimately, the root cause for me was a subquery returning more than one row - and the issue only appeared because for some reason, "bad data" got into the database - ie. that particular subquery should never have found a scenario where there is more than one row, and hence too, the error just began to appear one day. (For other people who are experiencing this error intermittently - it could be because it is only some of your queries - or one of your queries - that is failing).