Phát hiện bảng hoặc hàng bị khóa trong SQL Server


20

Tôi đang cố gắng hiểu / tìm hiểu cách theo dõi chi tiết của phiên bị chặn.

Vì vậy, tôi đã tạo ra các thiết lập sau:

create table foo (id integer not null primary key, some_data varchar(20));
insert into foo values (1, 'foo');
commit;

Bây giờ tôi kết nối với cơ sở dữ liệu hai lần từ hai khách hàng khác nhau.

Các vấn đề phiên đầu tiên:

begin transaction
update foo set some_data = 'update'
  where id = 1;

Tôi rõ ràng không cam kết ở đó để giữ các khóa.

Trong phiên thứ hai, tôi đưa ra tuyên bố tương tự và tất nhiên người ta chờ đợi do bị khóa. Bây giờ tôi đang cố gắng sử dụng các truy vấn khác nhau trôi nổi để xem phiên 2 đang chờ foobảng.

sp_who2 hiển thị như sau (Tôi đã xóa một số cột để chỉ hiển thị thông tin quan trọng):

SPID | Tình trạng | BlkBy | DBName | Lệnh | SPID | YÊU CẦU ID
----- + -------------- + ------- + ---------- + ---------- -------- + ------ + ----------
52 | ngủ | . | thức ăn | TUYỆT VỜI | 52 | 0        
53 | ngủ | . | thức ăn | TUYỆT VỜI | 53 | 0        
54 | XÁC NHẬN | 52 | thức ăn | CẬP NHẬT | 54 | 0        
56 | CHẠY | . | thức ăn | CHỌN VÀO | 56 | 0        

Điều này được mong đợi, phiên 54 bị chặn bởi những thay đổi không được cam kết từ phiên 52.

Truy vấn sys.dm_os_waiting_taskscũng cho thấy điều này. Tuyên bố:

select session_id, wait_type, resource_address, resource_description
from sys.dm_os_waiting_tasks
where blocking_session_id is not null;

trả về:

phiên_id | chờ đợi resource_address | resource_descrip                                                            
----------- + ----------- + -------------------- + ----- -------------------------------------------------- --------------------------
        54 | LCK_M_X | 0x000000002a35cd40 | khóa móc hobtid = 72057594046054400 dbid = 6 id = lock4ed1dd780 mode = X AssociObjectId = 72057594046054400

Một lần nữa điều này được mong đợi.

Vấn đề của tôi là, tôi không thể tìm ra cách tìm tên đối tượng thực tế mà phiên 54 đang chờ.

Tôi đã tìm thấy một số truy vấn đang tham gia sys.dm_tran_lockssys.dm_os_waiting_tasksnhư thế này:

SELECT ....
FROM sys.dm_tran_locks AS l
  JOIN sys.dm_os_waiting_tasks AS wt ON wt.resource_address = l.lock_owner_address

Nhưng trong kịch bản thử nghiệm ở trên của tôi, sự tham gia này không trả lại bất cứ điều gì. Vì vậy, tham gia đó là sai hoặc dm_tran_lockskhông thực sự chứa thông tin tôi đang tìm kiếm.

Vì vậy, điều tôi đang tìm kiếm là một truy vấn trả về một cái gì đó như:
" phiên 54 đang chờ khóa trong bảngfoo ".


Một số thông tin cơ bản:

Vấn đề thực tế mà tôi đang cố gắng giải quyết phức tạp hơn một chút, nhưng tập trung vào câu hỏi "trên bàn nào đang chờ phiên 54". Vấn đề được đề cập liên quan đến một thủ tục được lưu trữ lớn, cập nhật một số bảng và chọn từ một khung nhìn truy cập vào một số các bảng đó. Các selecttuyên bố bị chặn mặc dù chúng ta có cách ly bản chụp và đọc bản chụp cam kết kích hoạt. Tìm hiểu tại sao lựa chọn bị chặn (mà tôi nghĩ sẽ không thể thực hiện được nếu cách ly ảnh chụp nhanh được bật) sẽ là bước tiếp theo.

Bước đầu tiên tôi muốn tìm hiểu xem phiên đó đang chờ đợi điều gì .


msdn.microsoft.com/en-us/l Library / ms190345.aspx nói rằng sự tham gia của bạn là chính xác.
Max Vernon

@MaxVernon: cảm ơn vì đã xác nhận điều đó. Nhưng sau đó tôi còn bối rối hơn nữa. Tại sao nó không trả lại bất cứ thứ gì mặc dù tôi biết có khóa và phiên bị chặn?
a_horse_with_no_name

Tôi không thể tạo lại vấn đề bạn đang gặp trong SQL Server 2012. Tôi đã tạo cơ sở dữ liệu thử nghiệm, kích hoạt RCSI, tạo các bảng của bạn và chạy cả hai câu lệnh cập nhật và tôi thấy một hàng được trả về bởi truy vấn cuối cùng của bạn.
Max Vernon

Nếu bạn muốn có một trợ giúp trực quan trong việc phát hiện các khóa của mình, có một công cụ nguồn mở có tên là công cụ tìm khóa SQL. Bạn có thể tìm nguồn trên: github.com/LucBos/SqlLock Downloader Hoặc tải xuống tệp thực thi trên: sqllockfinder.com Chúng tôi cũng thích bất kỳ đóng góp nào bạn có thể thực hiện cho mã để chúng tôi có thể làm cho nó tốt hơn.
Luc Bos

Câu trả lời:


23

Tôi nghĩ rằng điều này làm những gì bạn cần.

USE 'yourDB'
GO
SELECT  
    OBJECT_NAME(p.[object_id]) BlockedObject
FROM    sys.dm_exec_connections AS blocking
    INNER JOIN sys.dm_exec_requests blocked
        ON blocking.session_id = blocked.blocking_session_id
    INNER JOIN sys.dm_os_waiting_tasks waitstats
        ON waitstats.session_id = blocked.session_id
    INNER JOIN sys.partitions p ON SUBSTRING(resource_description, 
        PATINDEX('%associatedObjectId%', resource_description) + 19, 
        LEN(resource_description)) = p.partition_id

3

Bạn có thể thử nó:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.