วิธีตรวจสอบว่ามีการล็อคตัวใดบนโต๊ะ


158

เราจะตรวจสอบการล็อคฐานข้อมูลที่จะใช้กับแถวใดเทียบกับชุดแบบสอบถามได้อย่างไร

เครื่องมือใด ๆ ที่เน้นการล็อคระดับแถวของตารางแบบเรียลไทม์?

DB: SQL Server 2005

คำตอบ:


118

เพื่อเพิ่มการตอบสนองอื่น ๆsp_lockนอกจากนี้ยังสามารถใช้ในการถ่ายโอนข้อมูลล็อคเต็มรูปแบบในกระบวนการที่ทำงานอยู่ทั้งหมด ผลลัพธ์อาจล้นหลาม แต่ถ้าคุณต้องการทราบอย่างแน่นอนว่าอะไรถูกล็อคมันเป็นสิ่งที่มีค่าในการทำงาน ฉันมักจะใช้มันพร้อมกับsp_who2ปลดล็อคปัญหาได้อย่างรวดเร็ว

มีsp_lockขั้นตอน"friendlier" ที่แตกต่างกันหลายแบบพร้อมใช้งานออนไลน์ขึ้นอยู่กับรุ่นของ SQL Server ที่เป็นปัญหา

ในกรณีของคุณสำหรับ SQL Server 2005 sp_lockยังคงมีอยู่ แต่เลิกใช้แล้วดังนั้นจึงแนะนำให้ใช้sys.dm_tran_locksมุมมองสำหรับสิ่งนี้ คุณสามารถค้นหาตัวอย่างของวิธีการ "ม้วนของคุณเอง" ฟังก์ชั่น sp_lock ที่นี่


116

นี่ไม่ใช่การแสดงให้คุณเห็นว่าแถวใดถูกล็อค แต่สิ่งนี้อาจเป็นประโยชน์กับคุณ

คุณสามารถตรวจสอบว่างบใดถูกบล็อกโดยใช้สิ่งนี้:

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

มันจะบอกคุณว่าแต่ละบล็อคกำลังรออะไรอยู่ ดังนั้นคุณสามารถติดตามได้ตลอดจนดูว่าประโยคใดทำให้เกิดบล็อกแรกที่ทำให้บล็อกอื่น ๆ

แก้ไขเพื่อเพิ่มความคิดเห็นจาก@MikeBlandford :

คอลัมน์ที่ถูกบล็อกหมายถึง spid ของกระบวนการบล็อก คุณสามารถเรียกใช้ kill {spid} เพื่อแก้ไขได้


7
คอลัมน์ที่ถูกบล็อกหมายถึง spid ของกระบวนการบล็อก คุณสามารถเรียกใช้ kill {spid} เพื่อแก้ไขได้
Mike Blandford

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

หากมีหลายอินสแตนซ์ของrequest_owner_typeเดียวกันอยู่คอลัมน์request_owner_idจะถูกใช้เพื่อแยกแยะแต่ละอินสแตนซ์ สำหรับธุรกรรมแบบกระจายคอลัมน์request_owner_typeและrequest_owner_guidจะแสดงข้อมูลเอนทิตีที่แตกต่างกัน

ตัวอย่างเช่น Session S1 เป็นเจ้าของล็อคแบบแบ่งใช้บน Table1 และทรานแซคชั่น T1 ซึ่งทำงานอยู่ในเซสชั่น S1 ก็มีล็อคแบบแชร์บน Table1 ในกรณีนี้คอลัมน์resource_descriptionที่ส่งคืนโดยsys.dm_tran_locksจะแสดงสองอินสแตนซ์ของทรัพยากรเดียวกัน 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 ออกใน profiler


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');
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.