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
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
Antworten:
Zum Hinzufügen zu den anderen Antworten sp_lock
kö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_who2
um Probleme mit dem Sperren schnell zu lösen.
sp_lock
Abhä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_lock
weiterhin verfügbar, jedoch veraltet. Daher wird jetzt empfohlen, die sys.dm_tran_locks
Ansicht 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 .
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.
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.
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;
sp_who2
und 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?
Sie können auch die integrierte sp_who2
gespeicherte 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.
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');