I'm trying to delete a database (from Sql Server Management Studio) and I receive this error:
Transaction (Process ID 52) was deadlocked on lock resources with
another process and has been chosen as the deadlock victim. Rerun the
transaction. (.Net SqlClient Data Provider)
I googled a lot (with a lot of result also here in so) but I cannot find any solution.
I really need to delete (and restore this db), but I'm stucked.
Any suggestion?
I guess you have open transactions. For example, for the database StackOverflow I am opening a transaction like this:
USE StackOverflow
BEGIN TRAN
and
USE StackOverflow
exec sp_whoisactive
So, when I try to deleted it:
I get the following error:
An exception occurred while executing a Transact-SQL statement or
batch. (Microsoft.SqlServer.ConnectionInfo)
Cannot drop database "StackOverflow" because it is currently in use.
(Microsoft SQL Server, Error: 3702)
If I choose close existing connections from the delete interface the database is successfully deleted.
Related
TLDR: I think SQL Server did not release a Sch-M lock and I can't release it or find the transaction holding the lock
I was trying to build a copy of another table and run some benchmarking on the data updates from disk, and when running a BULK INSERT on the empty table it errored out because I had used the wrong file name. I was running the script by selecting a large portion of text from a notepad in SQL Server Management Studio and hitting the Execute button. Now, no queries regarding the table whatsoever can execute, including things like OBJECT_ID or schema information in SQL Server Management Studio when manually refreshed. The queries just hang, and in the latter case SSMS gives an error about a lock not being relinquished within a timeout.
I have taken a few debugging steps so far.
I took a look at the sys.dm_tran_locks table filtered on the DB's resource ID. There, I can see a number of shared locks on the DB itself and some exclusive key locks, and exactly 1 lock on an object, a Sch-M lock. When I try and get the object name from the resource ID on the sys.dm_tran_locks table, the query hangs just like OBJECT_ID() does (and does not for other table names/IDs). The lock cites session ID 54.
I have also taken a look at the sys.dm_exec_requests table to try and find more information about SPID 54, but there are no rows with that session id. In fact, the only processes there are ones owned by sa and the single query checking the sys.dm_exec_requests table, owned by myself.
From this, if I understand everything correctly, it seems like somehow the BULK INSERT statement somehow failed to release the Sch-M lock that it takes.
So here are my questions: Why is there still a Sch-M lock on the table if the process that owns it seems to no longer exist? Is there some way to recover access to the table without restarting the SQL Server process? Would SQL code in the script after the BULK INSERT have run, but just on an empty table?
I am using SQL Server 2016 and SQL Server Management Studio 2016.
Question expression:
I am trying out a few things with regards to transactions. Consider the following operations:
Open a connection window 1 in SQL Server Management Studio
BEGIN a transaction, then delete about 2000 rows of data from table A
Open another connection window 2 in SQL Server Management Studio
Insert one new row of data into table A in window 2 (no transaction), it runs successfully right now
Then, I repeat the same operation, but in STEP 2 I delete 10k rows of data, in that case, STEP 4 can't run successfully. I had already waited for half an hour.
It shows that it is executing SQL...can't finish. Finally, I insert the data using connection window 1, it works right now.
Why does it work with 2k rows but not 10k rows?
The Sql sentence I execute:
In connection windows A, I execute
BEGIN TRAN
Delete from tableA (10K rows)
In connection windows B, I execute
Insert into tableA(..) VALUES (...)
windows B can't executes successfully.
Many thanks #Gordon
The cause:
I search the keyword about lock escalation.
I try to track lock escalation using SQL Server Profiler, and I get a
lock:escalation when I delete many data in a transaction(I don't commit or rollback).
So, I know the concept of lock escalation.
I delete too much data in a table ,then the row locks escalation to table escalation.I didn't commit or rollback them, other connection (or application)
can't access the table with table lock.
trace lock escalation in sql profiler
When the lock escalation happens in MSSQL Server
"The locks option also affects when lock escalation occurs. When locks is set to 0, lock escalation occurs when the memory used by the current lock structures reaches 40 percent of the Database Engine memory pool. When locks is not set to 0, lock escalation occurs when the number of locks reaches 40 percent of the value specified for locks."
How to set Using SQL Server Management Studio that will impact lock escalation:
To configure the locks option
In Object Explorer, right-click a server and select Properties .
Click the Advanced node.
Under Parallelism , type the desired value for the locks option.
Use the locks option to set the maximum number of available locks, such limiting the amount of memory SQL Server uses for them.
What you are experiencing is "lock escalation". By default, SQL Server uses (I think) row level locks for the delete. However if an expression has more than some threshold -- 5,000 locks -- then SQL Server escalates the locking to the entire table.
This is an automatic mechanism, which you can turn off if you need.
There is a lot of information about this, both in SQL Server documents and related documents.
This works, returning a resultset :
exec ('select ''col'', count(1) from test.dbo.[Table1] with (nolock)') at svrA
When I try to insert the resultset into a table:
insert into rowcount_sub (tablename,rowcnt)
exec ('select ''col'', count(1) from test.dbo.[Table1] with (nolock)') at svrA
Fails giving this error:
OLE DB provider "SQLNCLI10" for linked server "svrA" returned message "No transaction is active.".
Msg 7391, Level 16, State 2, Line 1
The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "svrA" was unable to begin a distributed transaction.
If you do not use distributed transaction on purpose, You can use advanced properties of the linked server object on main server to disable promotion of distributed transaction.
I was able to solve the same problem by using OPENQUERY instead of EXEC:
insert into rowcount_sub (tablename,rowcnt)
SELECT * FROM OPENQUERY(svrA, 'select ''col'', count(1) from test.dbo.[Table1] with (nolock)')
Hope it helps someone...
The operation could not be performed
because OLE DB provider "SQLNCLI10"
for linked server "svrA" was unable to
begin a distributed transaction.
The message is pretty clear and quite explicit. All you have to do is open your system documentation and follow the steps on configuring distributed transactions: Configuring MS DTC Services.
There are also plenty of blogs and tutorials out there:
How to configure DTC on Windows 2003
How to configure DTC on Windows 2008
Changing "Enable Promotion of Distributed Transaction" from True to false fixed my issue.
When running a stored procedure (from a .NET application) that does an INSERT and an UPDATE, I sometimes (but not that often, really) and randomly get this error:
ERROR [40001] [DataDirect][ODBC Sybase Wire Protocol driver][SQL Server]Your server command (family id #0, process id #46) encountered a deadlock situation. Please re-run your command.
How can I fix this?
Thanks.
Your best bet for solving you deadlocking issue is to set "print deadlock information" to on using
sp_configure "print deadlock information", 1
Everytime there is a deadlock this will print information about what processes were involved and what sql they were running at the time of the dead lock.
If your tables are using allpages locking. It can reduce deadlocks to switch to datarows or datapages locking. If you do this make sure to gather new stats on the tables and recreate indexes, views, stored procedures and triggers that access the tables that are changed. If you don't you will either get errors or not see the full benefits of the change depending on which ones are not recreated.
I have a set of long term apps which occasionally over lap table access and sybase will throw this error. If you check the sybase server log it will give you the complete info on why it happened. Like: The sql that was involved the two processes trying to get a lock. Usually one trying to read and the other doing something like a delete. In my case the apps are running in separate JVMs, so can't sychronize just have to clean up periodically.
Assuming that your tables are properly indexed (and that you are actually using those indexes - always worth checking via the query plan) you could try breaking the component parts of the SP down and wrapping them in separate transactions so that each unit of work is completed before the next one starts.
begin transaction
update mytable1
set mycolumn = "test"
where ID=1
commit transaction
go
begin transaction
insert into mytable2 (mycolumn) select mycolumn from mytable1 where ID = 1
commit transaction
go
We have 2 databases, say DB1 and DB2.
DB1 contains all the stored procedures which access also data in DB2.
DB1 uses synonyms to access the tables in DB2.
(Using synonyms is a requirement in our situation)
This works perfectly fine in all situations with SQL Server 2005 Developer Edition.
However in the Express Edition, we get an exception when we do the following:
1 Restart SQL Server
2 Execute the following code within DB1:
set transaction isolation level snapshot
begin transaction
declare #sQuery varchar(max)
set #sQuery = 'Select * from synToSomeTableInDB2'
exec (#sQuery)
commit transaction
This will result in the following error:
Snapshot isolation transaction failed in database '...' because the database was not recovered when the current transaction was started. Retry the transaction after the database has recovered.
The same select query passes fine when used without the EXEC or when run on the Developer Edition.
Restarting the server in step 1 is important as once a connection was made to DB2, the code runs also fine on SQL Server Express Edition.
Does anyone have an idea what this is? We need to be able to use EXEC for some dynamic queries.
We've already checked MSDN, searched Google, ...
Any help is greatly appreciated.
--- Edit: March 10 09
As discussed with Ed Harper below, I've filed a bug report for this.
See https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=422150
As found out via Microsoft Connect, the problem is that by default on SQL Server Express Edition the AUTO_CLOSE option is set on true.
Changing this option to false fixes the problem.
The error message suggests that the query fails because SQL server is still recovering the database following the service restart when you execute your query.
Does the error always occur on the first attempt to run this code, regardless of the time elapsed since the service was restarted?
Can you confirm from the SQL Server log that the database is recovering correctly after the restart?