Cara memeriksa kunci mana yang dipegang di atas meja

158

Bagaimana kita bisa memeriksa kunci basis data yang diterapkan pada baris mana terhadap kumpulan kueri?

Adakah alat yang menyoroti penguncian level baris tabel dalam waktu nyata?

DB: SQL Server 2005

usman shaheen
sumber

Jawaban:

118

Untuk menambah tanggapan lain, sp_lockjuga dapat digunakan untuk membuang informasi kunci penuh pada semua proses yang berjalan. Outputnya bisa luar biasa, tetapi jika Anda ingin tahu persis apa yang dikunci, itu yang berharga untuk dijalankan. Saya biasanya menggunakannya bersama dengan sp_who2dengan cepat membidik masalah penguncian.

Ada beberapa versi berbeda dari sp_lockprosedur "ramah" yang tersedia online, tergantung pada versi SQL Server yang dimaksud.

Dalam kasus Anda, untuk SQL Server 2005, sp_lockmasih tersedia, tetapi sudah usang, jadi sekarang disarankan untuk menggunakan sys.dm_tran_lockstampilan untuk hal semacam ini. Anda dapat menemukan contoh cara "menggulung fungsi sp_lock" Anda sendiri di sini .

mwigdahl
sumber
116

Ini tidak persis menunjukkan kepada Anda baris mana yang dikunci, tetapi ini mungkin membantu Anda.

Anda dapat memeriksa pernyataan mana yang diblokir dengan menjalankan ini:

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

Ini juga akan memberi tahu Anda apa yang menunggu setiap blok. Jadi, Anda bisa melacaknya sampai tuntas untuk melihat pernyataan mana yang menyebabkan blok pertama yang menyebabkan blok lainnya.

Edit untuk menambahkan komentar dari @MikeBlandford :

Kolom yang diblokir menunjukkan spid dari proses pemblokiran. Anda dapat menjalankan kill {spid} untuk memperbaikinya.

Brian R. Bondy
sumber
7
Kolom yang diblokir menunjukkan spid dari proses pemblokiran. Anda dapat menjalankan kill {spid} untuk memperbaikinya.
Mike Blandford
52

Anda dapat menemukan kunci saat ini di meja Anda dengan mengikuti kueri.

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

Lihat sys.dm_tran_locks

Jika ada beberapa instance dari request_owner_type yang sama , kolom request_owner_id digunakan untuk membedakan setiap instance. Untuk transaksi terdistribusi, kolom request_owner_type dan request_owner_guid akan menampilkan informasi entitas yang berbeda.

Misalnya, Sesi S1 memiliki kunci bersama di Table1; dan transaksi T1, yang berjalan di bawah sesi S1, juga memiliki kunci bersama pada Table1. Dalam hal ini, kolom resource_description yang dikembalikan oleh sys.dm_tran_locks akan menampilkan dua contoh dari sumber daya yang sama. The request_owner_type kolom akan menampilkan satu contoh sebagai sesi dan yang lainnya sebagai transaksi. Juga, kolom resource_owner_id akan memiliki nilai yang berbeda.

Somnath Muluk
sumber
36

Saya menggunakan Dynamic Management View (DMV) untuk menangkap kunci serta object_id atau partisi_id dari item yang dikunci.

(HARUS beralih ke Database yang ingin Anda amati untuk mendapatkan 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;
Jon
sumber
Saya mencoba menggunakan pernyataan ini untuk mencari tahu objek yang menunggu proses. Saya dapat dengan jelas melihat satu sesi menunggu yang lain menggunakan sp_who2dan dalam sys.dm_os_waiting_task(keduanya mencoba memperbarui tabel yang sama). Tetapi pernyataan Anda tidak mengembalikan baris. Ada ide?
a_horse_with_no_name
17

Anda juga dapat menggunakan sp_who2prosedur tersimpan bawaan untuk mendapatkan proses yang diblokir dan memblokir saat ini pada contoh SQL Server. Biasanya Anda akan menjalankan ini bersama contoh SQL Profiler untuk menemukan proses pemblokiran dan melihat perintah terbaru yang dikeluarkan spid di profiler.

Neil Barnwell
sumber
5

Anda dapat menemukan detailnya melalui skrip di bawah ini.

-- 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
sumber