So überprüfen Sie, welche Schlösser auf einem Tisch gehalten werden

158

Wie können wir überprüfen, welche Datenbanksperren auf welche Zeilen für einen Abfragebatch angewendet werden?

Gibt es ein Tool, das das Sperren auf Tabellenzeilenebene in Echtzeit hervorhebt?

DB: SQL Server 2005

usman shaheen
quelle

Antworten:

118

Zum Hinzufügen zu den anderen Antworten sp_lockkönnen auch vollständige Sperrinformationen für alle ausgeführten Prozesse ausgegeben werden. Die Ausgabe kann überwältigend sein, aber wenn Sie genau wissen möchten, was gesperrt ist, ist es eine wertvolle Ausgabe. Normalerweise benutze ich es zusammen mit, sp_who2um Probleme mit dem Sperren schnell zu lösen.

sp_lockAbhängig von der jeweiligen Version von SQL Server stehen online mehrere verschiedene Versionen "freundlicherer" Verfahren zur Verfügung.

In Ihrem Fall ist SQL Server 2005 sp_lockweiterhin verfügbar, jedoch veraltet. Daher wird jetzt empfohlen, die sys.dm_tran_locksAnsicht für diese Art von Dingen zu verwenden. Ein Beispiel dafür, wie Sie Ihre eigene sp_lock-Funktion "rollen" können, finden Sie hier .

mwigdahl
quelle
116

Dies zeigt Ihnen nicht genau, welche Zeilen gesperrt sind, aber dies kann für Sie hilfreich sein.

Sie können überprüfen, welche Anweisungen blockiert sind, indem Sie Folgendes ausführen:

select cmd,* from sys.sysprocesses
where blocked > 0

Außerdem erfahren Sie, worauf jeder Block wartet. Sie können dies also bis zum Ende verfolgen, um festzustellen, welche Anweisung den ersten Block verursacht hat, der die anderen Blöcke verursacht hat.

Bearbeiten , um einen Kommentar von @MikeBlandford hinzuzufügen :

Die blockierte Spalte zeigt die Geschwindigkeit des Blockierungsprozesses an. Sie können kill {spid} ausführen, um das Problem zu beheben.

Brian R. Bondy
quelle
7
Die blockierte Spalte zeigt die Geschwindigkeit des Blockierungsprozesses an. Sie können kill {spid} ausführen, um das Problem zu beheben.
Mike Blandford
52

Sie können aktuelle Sperren für Ihre Tabelle finden, indem Sie der Abfrage folgen.

USE yourdatabase;
GO

SELECT * FROM sys.dm_tran_locks
  WHERE resource_database_id = DB_ID()
  AND resource_associated_entity_id = OBJECT_ID(N'dbo.yourtablename');

Siehe sys.dm_tran_locks

Wenn mehrere Instanzen desselben request_owner_type vorhanden sind, wird die Spalte request_owner_id verwendet, um jede Instanz zu unterscheiden. Bei verteilten Transaktionen werden in den Spalten request_owner_type und request_owner_guid die verschiedenen Entitätsinformationen angezeigt .

Beispielsweise besitzt Sitzung S1 eine gemeinsame Sperre für Tabelle 1; und die Transaktion T1, die unter Sitzung S1 ausgeführt wird, besitzt auch eine gemeinsame Sperre für Tabelle 1. In diesem Fall wird die resource_description Spalte , die von zurückgegeben wird sys.dm_tran_locks wird zwei Instanzen derselben Ressource zeigen. In der Spalte request_owner_type wird eine Instanz als Sitzung und die andere als Transaktion angezeigt . Außerdem hat die Spalte resource_owner_id unterschiedliche Werte.

Somnath Muluk
quelle
36

Ich verwende eine dynamische Verwaltungsansicht (DMV), um Sperren sowie die Objekt- oder Partitions-ID des gesperrten Elements zu erfassen.

(MUSS zu der Datenbank wechseln, die Sie beobachten möchten, um object_id zu erhalten.)

SELECT 
     TL.resource_type,
     TL.resource_database_id,
     TL.resource_associated_entity_id,
     TL.request_mode,
     TL.request_session_id,
     WT.blocking_session_id,
     O.name AS [object name],
     O.type_desc AS [object descr],
     P.partition_id AS [partition id],
     P.rows AS [partition/page rows],
     AU.type_desc AS [index descr],
     AU.container_id AS [index/page container_id]
FROM sys.dm_tran_locks AS TL
INNER JOIN sys.dm_os_waiting_tasks AS WT 
 ON TL.lock_owner_address = WT.resource_address
LEFT OUTER JOIN sys.objects AS O 
 ON O.object_id = TL.resource_associated_entity_id
LEFT OUTER JOIN sys.partitions AS P 
 ON P.hobt_id = TL.resource_associated_entity_id
LEFT OUTER JOIN sys.allocation_units AS AU 
 ON AU.allocation_unit_id = TL.resource_associated_entity_id;
Jon
quelle
Ich versuche, diese Anweisung zu verwenden, um herauszufinden, auf welche Objekte ein Prozess wartet. Ich kann deutlich sehen, wie eine Sitzung mit sp_who2und in auf eine andere wartet sys.dm_os_waiting_task(beide versuchen, dieselbe Tabelle zu aktualisieren). Ihre Anweisung gibt jedoch keine Zeilen zurück. Irgendwelche Ideen?
a_horse_with_no_name
17

Sie können auch die integrierte sp_who2gespeicherte Prozedur verwenden, um aktuelle blockierte und blockierende Prozesse auf einer SQL Server-Instanz abzurufen. Normalerweise führen Sie dies zusammen mit einer SQL Profiler-Instanz aus, um einen Blockierungsprozess zu finden und den neuesten Befehl anzuzeigen, den spid im Profiler ausgegeben hat.

Neil Barnwell
quelle
5

Details finden Sie über das folgende Skript.

-- List all Locks of the Current Database 
SELECT TL.resource_type AS ResType 
      ,TL.resource_description AS ResDescr 
      ,TL.request_mode AS ReqMode 
      ,TL.request_type AS ReqType 
      ,TL.request_status AS ReqStatus 
      ,TL.request_owner_type AS ReqOwnerType 
      ,TAT.[name] AS TransName 
      ,TAT.transaction_begin_time AS TransBegin 
      ,DATEDIFF(ss, TAT.transaction_begin_time, GETDATE()) AS TransDura 
      ,ES.session_id AS S_Id 
      ,ES.login_name AS LoginName 
      ,COALESCE(OBJ.name, PAROBJ.name) AS ObjectName 
      ,PARIDX.name AS IndexName 
      ,ES.host_name AS HostName 
      ,ES.program_name AS ProgramName 
FROM sys.dm_tran_locks AS TL 
     INNER JOIN sys.dm_exec_sessions AS ES 
         ON TL.request_session_id = ES.session_id 
     LEFT JOIN sys.dm_tran_active_transactions AS TAT 
         ON TL.request_owner_id = TAT.transaction_id 
            AND TL.request_owner_type = 'TRANSACTION' 
     LEFT JOIN sys.objects AS OBJ 
         ON TL.resource_associated_entity_id = OBJ.object_id 
            AND TL.resource_type = 'OBJECT' 
     LEFT JOIN sys.partitions AS PAR 
         ON TL.resource_associated_entity_id = PAR.hobt_id 
            AND TL.resource_type IN ('PAGE', 'KEY', 'RID', 'HOBT') 
     LEFT JOIN sys.objects AS PAROBJ 
         ON PAR.object_id = PAROBJ.object_id 
     LEFT JOIN sys.indexes AS PARIDX 
         ON PAR.object_id = PARIDX.object_id 
            AND PAR.index_id = PARIDX.index_id 
WHERE TL.resource_database_id  = DB_ID() 
      AND ES.session_id <> @@Spid -- Exclude "my" session 
      -- optional filter  
      AND TL.request_mode <> 'S' -- Exclude simple shared locks 
ORDER BY TL.resource_type 
        ,TL.request_mode 
        ,TL.request_type 
        ,TL.request_status 
        ,ObjectName 
        ,ES.login_name;



--TSQL commands
SELECT 
       db_name(rsc_dbid) AS 'DATABASE_NAME',
       case rsc_type when 1 then 'null'
                             when 2 then 'DATABASE' 
                             WHEN 3 THEN 'FILE'
                             WHEN 4 THEN 'INDEX'
                             WHEN 5 THEN 'TABLE'
                             WHEN 6 THEN 'PAGE'
                             WHEN 7 THEN 'KEY'
                             WHEN 8 THEN 'EXTEND'
                             WHEN 9 THEN 'RID ( ROW ID)'
                             WHEN 10 THEN 'APPLICATION' end  AS 'REQUEST_TYPE',

       CASE req_ownertype WHEN 1 THEN 'TRANSACTION'
                                     WHEN 2 THEN 'CURSOR'
                                     WHEN 3 THEN 'SESSION'
                                     WHEN 4 THEN 'ExSESSION' END AS 'REQUEST_OWNERTYPE',

       OBJECT_NAME(rsc_objid ,rsc_dbid) AS 'OBJECT_NAME', 
       PROCESS.HOSTNAME , 
       PROCESS.program_name , 
       PROCESS.nt_domain , 
       PROCESS.nt_username , 
       PROCESS.program_name ,
       SQLTEXT.text 
FROM sys.syslockinfo LOCK JOIN 
     sys.sysprocesses PROCESS
  ON LOCK.req_spid = PROCESS.spid
CROSS APPLY sys.dm_exec_sql_text(PROCESS.SQL_HANDLE) SQLTEXT
where 1=1
and db_name(rsc_dbid) = db_name()



--Lock on a specific object
SELECT * 
FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID()
AND resource_associated_entity_id = object_id('Specific Table');
Metin Atalay
quelle