Ngủ SPID chặn các giao dịch khác


16

Tôi thực sự gặp khó khăn khi theo dõi một số chặn chúng tôi đang gặp phải.

Trạng thái chặn SPID gốc là 'ngủ', cmd là 'TUYỆT VỜI', và sqltextSET TRANSACTION ISOLATION LEVEL READ COMMITTED.

Khi tôi xem báo cáo Số lượng giao dịch hàng đầu theo số lượng giao dịch bị chặn, Câu lệnh SQL chặn là '-'.

Tôi đã thực hiện theo dõi trên SQL và khi việc chặn xảy ra truy tìm SPID chặn gốc nhưng nó thực sự không dẫn tôi đến bất cứ đâu. Các tuyên bố dấu vết cuối cùng là giống như sqltexttrên SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

Tôi đã kiểm tra tất cả các thủ tục được lưu trữ có liên quan mà tôi có thể tìm thấy để đảm bảo rằng chúng có các câu lệnh TRY / CATCH BEGIN TRAN / CAMIT TRAN / ROLLBACK TRAN (chúng tôi sử dụng các thủ tục được lưu trữ cho mọi thứ để không có câu lệnh độc lập nào được chạy). Vấn đề này mới chỉ bắt đầu xảy ra trong 24 giờ qua và không ai tuyên bố đã thực hiện bất kỳ thay đổi nào đối với hệ thống.

Giải pháp: một trong những quy trình được lưu trữ ít được sử dụng của chúng tôi có lỗi với phần chèn (số cột không khớp), nhưng chúng tôi vẫn bối rối về chính xác những gì đang xảy ra.

Khi xem xét tất cả các thông tin theo dõi, câu lệnh EXEC cho quy trình được lưu trữ này đã được liệt kê đôi khi, nhưng KHÔNG BAO GIỜ ngay trước khi BLOCK xảy ra trên SPID chặn. Có vẻ như khi nó bắt đầu chặn, dấu vết đã không ghi lại việc thực hiện nó (hoặc bất kỳ câu lệnh nào trong đó). Tuy nhiên, có những lần khác, dấu vết đã ghi lại việc thực thi và không có sự ngăn chặn nào xảy ra.

Báo cáo lỗi thủ tục được lưu trữ đến từ một người dùng và tôi có thể tìm thấy nhiều câu lệnh EXEC trong dấu vết và chạy chúng trong SSMS. Không có thời gian khi tôi chạy chúng, chúng tôi có bất kỳ chặn nào xảy ra hoặc chúng bị treo. Họ đã chạy như mong đợi (khối bắt được bắn và khôi phục giao dịch sau lỗi). Sau khi giải quyết các sửa chữa thủ tục được lưu trữ, chúng tôi đã không thấy vấn đề một lần nữa.


Tôi đang giả sử tên máy chủ của SPID chặn không giúp được gì cả?
Jon Seigel

Không, đó chỉ là IP của một trong những máy chủ web của chúng tôi ... Chúng tôi có một ý tưởng khác để thay đổi mỗi lần đăng nhập SQL cho mỗi cuộc gọi XUÂN trong quá trình đăng nhập / đăng ký (mà chúng tôi cảm thấy là lỗi xảy ra) thành một tên người dùng riêng biệt có thể xảy ra giúp chúng tôi cách ly mà XUÂN có thể gây ra sự ngăn chặn.
Brad

1
TRY / CATCH sẽ không bắt lỗi biên dịch và chèn cột không khớp sẽ là lỗi biên dịch như vậy. Điều này cũng sẽ không bao giờ kích hoạt nhiều sự kiện hồ sơ XX: Đã hoàn thành.
Remus Rusanu

1
Đây thực sự không phải là lỗi biên dịch trong trường hợp này vì nhà phát triển thiên tài đã sử dụng INSERT INTO [bảng] CHỌN * từ [othertable] và nó không bị bắt ngang hàng. Tôi đã điều hành XUÂN phát triển 1000 lần từ ColdFusion trong 3 phiên đồng thời và nó không bao giờ để lại một giao dịch giống như khi sản xuất.
Brad

Câu trả lời:


10

Từ các bình luận, tôi đoán bạn đã hết thời gian chờ phía máy khách đã hủy bỏ truy vấn SQL. Điều này không phục hồi giao dịch vì kết nối vẫn mở trên SQL Server do nhóm kết nối.

Vì vậy, bạn cần sử dụng SET XACT_ABORT ON hoặc thêm một số mã khôi phục ứng dụng khách

Xem Hết thời gian giao dịch máy chủ SQL để biết tất cả các chi tiết chính


Tất cả các XUÂN của chúng tôi chứa các khối TRY / CATCH và các câu lệnh BEGIN TRAN / CAMIT TRAN / ROLLBACK TRAN, ROLLBACK nằm trong CATCH. XACT_ABORT vẫn có hiệu lực?
Brad

@Brad: vâng. Xem liên kết của tôi. Khối bắt không được nhấn vào CommandTimeout
gbn

gbn: Cảm ơn. Tôi vẫn còn bối rối. Các kết nối của chúng tôi được đặt thành không bao giờ hết thời gian (0). Vì vậy, bạn đang nói rằng nếu chúng tôi sử dụng lại các kết nối và một kết nối chạy XUÂN có lỗi (có các khối TRY / CATCH và TRAN), thì bằng cách nào đó, nó không bao giờ có thể chạy ROLLBACK trong khối CATCH do đó khóa các bảng và giữ giao dịch mở? Điều đó không có ý nghĩa với tôi.
Brad

@Brad: Một XUÂN có lỗi sẽ đánh vào khối CATCH. Tôi không nói khác hay khác. Nhưng liên kết của tôi cho biết điều gì sẽ xảy ra nếu bạn có CommandTimeout, khác với ConnectionTimeout. Máy khách nói "hủy bỏ" và SQL Server dừng xử lý. Ergo, khối CATCH hoặc rollback hoặc cam kết không bao giờ bị tấn công
gbn

Tôi không nghĩ rằng chúng tôi có một CommandTimeout được chỉ định. Tất cả các thủ tục được lưu trữ của chúng tôi đang thử nghiệm bằng cách sử dụng sqlstress và phải thực hiện dưới 1000ms ở 10 người dùng 10 lần lặp (tối thiểu). Tôi vẫn rất bối rối về những gì đã xảy ra, nhưng tôi đang cập nhật câu hỏi với những gì chúng tôi tìm thấy là vấn đề.
Brad

9

Sử dụng most_recent_sql_handle trong sys.dm_exec_connections để xem câu lệnh cuối cùng được thực thi.

SELECT  t.text,
        QUOTENAME(OBJECT_SCHEMA_NAME(t.objectid, t.dbid)) + '.'
        + QUOTENAME(OBJECT_NAME(t.objectid, t.dbid)) proc_name,
        c.connect_time,
        s.last_request_start_time,
        s.last_request_end_time,
        s.status
FROM    sys.dm_exec_connections c
JOIN    sys.dm_exec_sessions s
        ON c.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) t
WHERE   c.session_id = 72;--your blocking spid

Ngoài ra, kiểm tra nếu có một giao dịch mở cho spid đó

SELECT  st.transaction_id,
        at.name,
        at.transaction_begin_time,
        at.transaction_state,
        at.transaction_status
FROM    sys.dm_tran_session_transactions st
JOIN    sys.dm_tran_active_transactions at
        ON st.transaction_id = at.transaction_id
WHERE   st.session_id = 72;--your blocking spid

Bạn cũng có thể sử dụng DBCC INPUTBUFFER(spid)để xem SQL cuối cùng được thực thi.
Mike Fal

Tôi đã sử dụng tất cả những thứ đó và lệnh cuối cùng luôn là thứ tôi đặt trong bài viết gốc của mình: THIẾT LẬP CẤP PHÂN TÍCH GIAO DỊCH GIAO DỊCH. Tôi cũng đã chạy DBCC OPENTRAN và có thể thấy rằng có một giao dịch mở cho việc chặn PID.
Brad

Lựa chọn đầu tiên của tôi cũng cung cấp cho bạn tên thủ tục, nếu câu lệnh thực sự là một phần của thủ tục.
Sebastian Meine

Tôi đảm bảo với bạn rằng chúng tôi không sử dụng truy vấn adhoc từ các máy chủ web của chúng tôi và khi tôi chạy truy vấn đầu tiên đó, ngay cả khi không có mệnh đề WHERE, tôi chỉ nhận được XUÂN có tên trong một số phiên SQL, phần còn lại là cột NULL.
Brad

Tôi nhận thấy rằng tôi có rất nhiều phiên nói rằng 'THIẾT LẬP CẤP PHÂN TÍCH GIAO DỊCH GIAO DỊCH' và tất cả chúng đều từ ColdFusion (tập lệnh chính được sử dụng trên các máy chủ web của chúng tôi). Có lẽ ColdFusion khi nhàn rỗi phát hành câu lệnh giữ kết nối mở (vì nó được đặt để giữ kết nối mở).
Brad

4

Bạn đã thử sử dụng sp_whoisactive của Adam Machanic chưa? Có một tùy chọn để nhận lệnh bên ngoài để xem nếu nó thực sự nằm trong một Proc. Nó có thể là ứng dụng đang mở một giao dịch thay vì cam kết nó. Hãy thử nhìn vào DBCC OPENTRAN .


Cảm ơn DBCC OPENTRAN. Nó cho tôi biết rằng bộ chặn PID có giao dịch mở, nhưng không có thêm thông tin chi tiết nào. sp_whoisactive trả về cùng một thông tin về quy trình bị chặn như tôi đã có thể tự mình lấy. Vẫn chưa có thông tin chi tiết về những gì đang diễn ra ngoài 'THIẾT LẬP CẤP PHÂN TÍCH GIAO DỊCH GIAO DỊCH'
Brad
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.