I have a SQL table that all of a sudden cannot return data unless I include with (nolock)
on the end, which indicates some kind of lock left on my table.
I've experimented a bit with sys.dm_tran_locks to identify that there are in fact a number of locks on the table, but how do I identify what is locking them (ie the request element of the sys.dm_tran_locks )?
EDIT: I know about sp_lock for pre SQL 2005, but now that that sp is deprecated, AFAIK the right way to do this is with sys.dm_tran_locks . I'm using SQL Server 2008 R2.
9条答案
按热度按时间xtfmy6hx1#
Take a look at the following system stored procedures, which you can run in SQLServer Management Studio (SSMS):
Also, in SSMS, you can view locks and processes in different ways:
Different versions of SSMS put the activity monitor in different places. For example, SSMS 2008 and 2012 have it in the context menu when you right-click on a server node.
tct7dpnv2#
For getting straight to "who is blocked/blocking" I combined/abbreviated sp_who and sp_lock into a single query which gives a nice overview of who has what object locked to what level.
(For what the lock level abbreviations mean, see e.g. https://technet.microsoft.com/en-us/library/ms175519%28v=sql.105%29.aspx )
Copied from: sp_WhoLock – a T-SQL stored proc combining sp_who and sp_lock...
NB the [Xclusive lock for command] column can be misleading -- it shows the current command for that spid; but the X lock could have been triggered by an earlier command in the transaction.
rwqw0loc3#
This query should give you existing locks.
Having spids, you could check activity monitor(processes tab) to find out what processes are locking the tables ("details" for more info and "kill process" to kill it).
sd2nnvve4#
I have a stored procedure that I have put together, that deals not only with locks and blocking, but also to see what is running in a server. I have put it in master. I will share it with you, the code is below:
this procedure has done very good for me in the last couple of years. to run it just type sp_radhe
Regarding putting sp_radhe in the master database
I use the following code and make it a system stored procedure
as you can see on the link below
Creating Your Own SQL Server System Stored Procedures
Regarding the transaction isolation level
Questions About T-SQL Transaction Isolation Levels You Were Too Shy to Ask
Jonathan Kehayias
Once you change the transaction isolation level it only changes when the scope exits at the end of the procedure or a return call, or if you change it explicitly again using SET TRANSACTION ISOLATION LEVEL.
In addition the TRANSACTION ISOLATION LEVEL is only scoped to the stored procedure, so you can have multiple nested stored procedures that execute at their own specific isolation levels.
v2g6jxz65#
This should give you all the details of the existing locks.
You can then kill, with caution, the SPID that blocks your table.
kfgdxczn6#
You can also use
sp_who2
which gives more informationHere is some info http://dbadiaries.com/using-sp_who2-to-help-with-sql-server-troubleshooting
chhqkbe17#
A colleague and I have created a tool just for this. It's a visual representation of all the locks that your sessions produce. Give it a try ( http://www.sqllockfinder.com ), it's open source ( https://github.com/LucBos/SqlLockFinder )
nwnhqdif8#
As per the official docs the sp_lock is mark as deprecated:
This feature is in maintenance mode and may be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.
and it is recommended to use sys.dm_tran_locks instead. This dynamic management object returns information about currently active lock manager resources. Each row represents a currently active request to the lock manager for a lock that has been granted or is waiting to be granted.
It generally returns more details in more user friendly syntax then
sp_lock
does.The whoisactive routine written by Adam Machanic is very good to check the current activity in your environment and see what types of waits/locks are slowing your queries. You can very easily find what is blocking your queries and tons of other handy information.
For example, let's say we have the following queries running in the default SQL Server Isolation Level - Read Committed. Each query is executing in separate query window:
Then execute the
sp_whoisactive
(only part of the columns are displayed):You can easily seen the session which is blocking the
SELECT
statement and even its T-SQL code. The routine has a lot of parameters, so you can check the docs for more details.If we query the
sys.dm_tran_locks
view we can see that one of the session is waiting for a share lock of a resource, that has exclusive lock by other session:cbwuti449#
Plot twist!
You can have orphaned distributed transactions holding exclusive locks and you will not see them if your script assumes there is a session associated with the transaction (there isn't!). Run the script below to identify these transactions:
Once you have identified the transaction, use the transaction_uow column to find it in MSDTC and decide whether to abort or commit it. If the transaction is marked as In Doubt (with a question mark next to it) you will probably want to abort it.
You can also kill the Unit Of Work (UOW) by specifying the transaction_uow in the KILL command:
References:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/kill-transact-sql?view=sql-server-2017#arguments
https://www.mssqltips.com/sqlservertip/4142/how-to-kill-a-blocking-negative-spid-in-sql-server/