Bir tabloda hangi kilitlerin tutulduğunu kontrol etme


159

Bir sorgu kümesine karşı hangi satırlara hangi veritabanı kilitlerinin uygulandığını nasıl kontrol edebiliriz?

Gerçek zamanlı olarak tablo satır düzeyinde kilitleme vurgulayan herhangi bir araç?

DB: SQL Server 2005

Yanıtlar:


118

Diğer yanıtlara eklemek için, sp_lockçalışan tüm işlemlere tam kilit bilgilerini dökmek için de kullanılabilir. Çıktı çok zor olabilir, ancak tam olarak neyin kilitli olduğunu bilmek istiyorsanız, çalıştırmak için değerli bir değerdir. Genellikle sp_who2kilitleme problemlerini hızlıca sıfırlamak için birlikte kullanırım .

sp_lockSöz konusu SQL Server sürümüne bağlı olarak, çevrimiçi olarak kullanılabilen "daha kolay" prosedürlerin birden fazla farklı sürümü vardır .

Sizin durumunuzda, SQL Server 2005 sp_lockiçin hala kullanılabilir, ancak kullanımdan kaldırılmıştır, bu nedenle şimdi sys.dm_tran_locksbu tür bir şey için görünümü kullanmanız önerilir . Sp_lock fonksiyonunun nasıl "döndürüleceğine" dair bir örnek burada bulabilirsiniz .


116

Bu, tam olarak hangi satırların kilitli olduğunu göstermez, ancak bu size yardımcı olabilir.

Bunu çalıştırarak hangi ifadelerin engellendiğini kontrol edebilirsiniz:

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

Ayrıca her bloğun ne beklediğini size söyleyecektir. Böylece, hangi ifadenin diğer bloklara neden olan ilk bloğa neden olduğunu görmek için sonuna kadar izleyebilirsiniz.

Düzenleme gelen Yorum eklemek için @MikeBlandford :

Engellenen sütun, engelleme işleminin hızını gösterir. Düzeltmek için kill {spid} çalıştırabilirsiniz.


7
Engellenen sütun, engelleme işleminin hızını gösterir. Düzeltmek için kill {spid} çalıştırabilirsiniz.
Mike Blandford

53

Geçerli kilitleri aşağıdaki sorguyu kullanarak tablonuzda bulabilirsiniz .

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');

Bkz. Sys.dm_tran_locks

Aynı request_owner_type öğesinin birden çok örneği varsa, her örneği ayırt etmek için request_owner_id sütunu kullanılır. Dağıtılmış işlemler için request_owner_type ve request_owner_guid sütunlarında farklı varlık bilgileri gösterilir.

Örneğin, S1 oturumu Tablo1'de paylaşılan bir kilide sahiptir; ve S1 oturumu altında çalışan T1 işleminin de Tablo1'de paylaşılan bir kilidi vardır. Bu durumda, sys.dm_tran_locks tarafından döndürülen resource_description sütunu aynı kaynağın iki örneğini gösterir. Request_owner_type sütun, bir oturum olarak örneği ve bir işlem olarak diğer gösterecektir. Ayrıca resource_owner_id sütununun farklı değerleri olacaktır.


36

Kilitleri ve kilitli öğenin object_id veya partition_id kilitlerini yakalamak için bir Dinamik Yönetim Görünümü (DMV) kullanın.

(Object_id almak için gözlemlemek istediğiniz Veritabanına geçmeniz GEREKİR)

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;

Bir işlemin beklediği nesneleri bulmak için bu ifadeyi kullanmaya çalışıyorum. Açıkça bir oturum kullanarak sp_who2ve içinde sys.dm_os_waiting_task(her ikisi de aynı tabloyu güncellemeye çalışırken) bekleyen başka bir görebilirsiniz . Ancak ifadeniz herhangi bir satır döndürmüyor. Herhangi bir fikir?
a_horse_with_no_name

17

sp_who2Bir SQL Server örneğinde geçerli engellenen ve engelleme işlemlerini almak için yerleşik saklı yordamı da kullanabilirsiniz . Genellikle bunu bir engelleme işlemi bulmak için SQL Profiler örneğiyle birlikte çalıştırır ve profiler'de verilen spid'in en son komutuna bakarsınız.


5

Ayrıntıları aşağıdaki komut dosyası aracılığıyla bulabilirsiniz.

-- 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');
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.