Як перевірити, які замки тримаються на столі


158

Як ми можемо перевірити, які блоки застосовано до баз даних, у яких рядках щодо групи запитів?

Будь-який інструмент, який висвітлює блокування рівня рядків таблиці в режимі реального часу?

БД: SQL Server 2005

Відповіді:


118

Щоб додати до інших відповідей, sp_lockтакож можна використовувати для скидання повної інформації про блокування про всі запущені процеси. Вихід може бути вражаючим, але якщо ви хочете точно знати, що заблоковано, це варто запустити. Я зазвичай використовую його разом із тим, sp_who2щоб швидко зняти нульові проблеми при блокуванні.

Існує декілька різних версій "дружніших" sp_lockпроцедур, доступних в Інтернеті, залежно від розглянутих версій SQL Server.

У вашому випадку для SQL Server 2005 sp_lockвсе ще доступний, але застарілий, тому зараз рекомендується використовувати sys.dm_tran_locksвигляд для подібних речей. Ви можете знайти приклад того, як "скочувати власну" функцію sp_lock тут .


116

Це не точно показує вам, які рядки заблоковані, але це може вам допомогти.

Ви можете перевірити, які оператори заблоковані, виконавши це:

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

Він також розповість, що чекає кожен блок. Таким чином, ви можете простежити це до кінця, щоб побачити, який вислів викликав перший блок, який спричинив інші блоки.

Редагувати, щоб додати коментар від @MikeBlandford :

Заблокований стовпець вказує на спід процесу блокування. Ви можете запустити kill {spid}, щоб виправити це.


7
Заблокований стовпець вказує на процес блокування. Ви можете запустити kill {spid}, щоб виправити це.
Майк Бландфорд

52

Ви можете знайти поточні блокування на своєму столі , дотримуючись запитів.

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

Див. Sys.dm_tran_locks

Якщо існує декілька примірників одного і того ж запиту_owner_type , стовпець request_owner_id використовується для розмежування кожного примірника. Для розподілених транзакцій запит_власник_тип та запит_власник_гуд стовпці показуватимуть різну інформацію про сутність.

Наприклад, сесії S1 належить загальний замок на Table1; і транзакція T1, яка працює під час сеансу S1, також володіє спільним блокуванням на Table1. У цьому випадку у стовпці " опис ресурсів ", який повертається sys.dm_tran_locks, будуть показані два екземпляри одного і того ж ресурсу. The стовпці request_owner_type буде показано один екземпляр як сеанс, а інший - як транзакція. Також стовпець resource_owner_id матиме різні значення.


36

Я використовую динамічний перегляд управління (DMV) для зйомки замків, а також object_id або partition_id елемента, який заблокований.

(ОБОВ'ЯЗКОВО переключитися на базу даних, яку ви хочете спостерігати, щоб отримати object_id)

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та в sys.dm_os_waiting_task(обидва намагаються оновити ту саму таблицю). Але ваша заява не повертає жодних рядків. Будь-які ідеї?
a_horse_with_no_name

17

Ви також можете використовувати вбудовану sp_who2збережену процедуру для отримання поточних блокованих та блокуючих процесів на екземплярі SQL Server. Як правило, ви запускаєте це поряд із екземпляром SQL Profiler, щоб знайти процес блокування та переглянути останню команду, що spid видав у профілі.


5

Ви можете знайти деталі за допомогою наведеного нижче сценарію.

-- 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');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.