如何find什么是locking我的表

我有一个SQL表,突然之间不能返回数据,除非我在结尾包含“(nolock)”,这表明某种锁在我的表上。 我已经用dm_tran_locks做了一些尝试,以确定表中有多less个锁,但是如何识别locking它们的内容(即dm_tran_locks的请求元素)?

编辑:我知道关于pre SQL 2005 sp_lock,但现在,该sp已被弃用,AFAIK正确的方式来做到这一点与dm_tran_locks。 我正在使用SQL Server 2008 R2。

查看下面的系统存储过程,可以在SQLServer Management Studio(SSMS)中运行这些存储过程:

  • sp_who的
  • sp_lock的

另外,在SSMS中,您可以用不同的方式查看锁和进程:

在这里输入图像说明

不同版本的SSMS将活动监视器放在不同的地方。 例如,SSMS 2008和2012在右键单击服务器节点时在上下文菜单中有。

为了直接find“谁被阻止/阻止”,我将sp_who和sp_lock缩写为一个单独的查询,这个查询很好地概括了谁将哪个对象locking到什么级别。

--Create Procedure WhoLock --AS if object_id('tempdb..#locksummary') is not null Drop table #locksummary if object_id('tempdb..#lock') is not null Drop table #lock create table #lock ( spid int, dbid int, objId int, indId int, Type char(4), resource nchar(32), Mode char(8), status char(6)) Insert into #lock exec sp_lock if object_id('tempdb..#who') is not null Drop table #who create table #who ( spid int, ecid int, status char(30), loginame char(128), hostname char(128), blk char(5), dbname char(128), cmd char(16) -- , request_id INT --Needed for SQL 2008 onwards -- ) Insert into #who exec sp_who Print '-----------------------------------------' Print 'Lock Summary for ' + @@servername + ' (excluding tempdb):' Print '-----------------------------------------' + Char(10) Select left(loginame, 28) as loginame, left(db_name(dbid),128) as DB, left(object_name(objID),30) as object, max(mode) as [ToLevel], Count(*) as [How Many], Max(Case When mode= 'X' Then cmd Else null End) as [Xclusive lock for command], l.spid, hostname into #LockSummary from #lock l join #who w on l.spid= w.spid where dbID != db_id('tempdb') and l.status='GRANT' group by dbID, objID, l.spid, hostname, loginame Select * from #LockSummary order by [ToLevel] Desc, [How Many] Desc, loginame, DB, object Print '--------' Print 'Who is blocking:' Print '--------' + char(10) SELECT p.spid ,convert(char(12), d.name) db_name , program_name , p.loginame , convert(char(12), hostname) hostname , cmd , p.status , p.blocked , login_time , last_batch , p.spid FROM master..sysprocesses p JOIN master..sysdatabases d ON p.dbid = d.dbid WHERE EXISTS ( SELECT 1 FROM master..sysprocesses p2 WHERE p2.blocked = p.spid ) Print '--------' Print 'Details:' Print '--------' + char(10) Select left(loginame, 30) as loginame, l.spid, left(db_name(dbid),15) as DB, left(object_name(objID),40) as object, mode , blk, l.status from #lock l join #who w on l.spid= w.spid where dbID != db_id('tempdb') and blk <>0 Order by mode desc, blk, loginame, dbID, objID, l.status 

(有关locking级别缩写的含义,请参阅https://technet.microsoft.com/en-us/library/ms175519%28v=sql.105%29.aspx

从以下版本复制: sp_WhoLock – 结合了sp_who和sp_lock的T-SQL存储过程

注意[Xclusive lock for command]列可能会引起误解 – 显示当前的spid命令; 但是X锁可能是由事务中的早期命令触发的。

 exec sp_lock 

这个查询应该给你现有的锁。

 exec sp_who SPID -- will give you some info 

有spids,你可以检查活动监视器(进程选项卡),找出哪些进程locking表(“细节”更多信息和“杀死进程”杀死它)。

我有一个存储过程,我已经放在一起,不仅处理锁和阻塞,而且还看到在服务器中运行。 我已经把它放在主人。 我将与你分享,代码如下:

 USE [master] go CREATE PROCEDURE [dbo].[sp_radhe] AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED -- the current_processes -- marcelo miorelli -- CCHQ -- 04 MAR 2013 Wednesday SELECT es.session_id AS session_id ,COALESCE(es.original_login_name, '') AS login_name ,COALESCE(es.host_name,'') AS hostname ,COALESCE(es.last_request_end_time,es.last_request_start_time) AS last_batch ,es.status ,COALESCE(er.blocking_session_id,0) AS blocked_by ,COALESCE(er.wait_type,'MISCELLANEOUS') AS waittype ,COALESCE(er.wait_time,0) AS waittime ,COALESCE(er.last_wait_type,'MISCELLANEOUS') AS lastwaittype ,COALESCE(er.wait_resource,'') AS waitresource ,coalesce(db_name(er.database_id),'No Info') as dbid ,COALESCE(er.command,'AWAITING COMMAND') AS cmd ,sql_text=st.text ,transaction_isolation = CASE es.transaction_isolation_level WHEN 0 THEN 'Unspecified' WHEN 1 THEN 'Read Uncommitted' WHEN 2 THEN 'Read Committed' WHEN 3 THEN 'Repeatable' WHEN 4 THEN 'Serializable' WHEN 5 THEN 'Snapshot' END ,COALESCE(es.cpu_time,0) + COALESCE(er.cpu_time,0) AS cpu ,COALESCE(es.reads,0) + COALESCE(es.writes,0) + COALESCE(er.reads,0) + COALESCE(er.writes,0) AS physical_io ,COALESCE(er.open_transaction_count,-1) AS open_tran ,COALESCE(es.program_name,'') AS program_name ,es.login_time FROM sys.dm_exec_sessions es LEFT OUTER JOIN sys.dm_exec_connections ec ON es.session_id = ec.session_id LEFT OUTER JOIN sys.dm_exec_requests er ON es.session_id = er.session_id LEFT OUTER JOIN sys.server_principals sp ON es.security_id = sp.sid LEFT OUTER JOIN sys.dm_os_tasks ota ON es.session_id = ota.session_id LEFT OUTER JOIN sys.dm_os_threads oth ON ota.worker_address = oth.worker_address CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS st where es.is_user_process = 1 and es.session_id <> @@spid and es.status = 'running' ORDER BY es.session_id end GO 

这个程序在过去几年对我来说是非常好的。 运行它只需键入sp_radhe

关于把sp_radhe放在主数据库中

我使用下面的代码,并使其成为一个系统存储过程

 exec sys.sp_MS_marksystemobject 'sp_radhe' 

正如你可以看到下面的链接

创build您自己的SQL Server系统存储过程

关于事务隔离级别

关于T-SQL事务隔离级别的问题,您可能不敢问

乔纳森Kehayias

一旦更改了事务隔离级别,它只会在范围在过程结束或返callback用时退出时发生更改,或者如果使用SET TRANSACTION ISOLATION LEVEL再次显式更改。

另外,TRANSACTION ISOLATION LEVEL只限于存储过程的范围,所以你可以有多个嵌套的存储过程在它们自己特定的隔离级别上执行。

你也可以使用sp_who2来提供更多的信息

以下是一些信息http://dbadiaries.com/using-sp_who2-to-help-with-sql-server-troubleshooting