Mở rộng câu trả lời của Mark ...
Khi xảy ra sự kiện hết thời gian máy khách (ví dụ .net CommandTimeout), máy khách sẽ gửi "ABORT" tới SQL Server. SQL Server sau đó chỉ cần bỏ qua xử lý truy vấn. Không có giao dịch được khôi phục, không có khóa được phát hành.
Bây giờ, kết nối được trả về nhóm kết nối, vì vậy nó không bị đóng trên SQL Server. Nếu điều này từng xảy ra (thông qua KILL hoặc máy khách khởi động lại, v.v.) thì các giao dịch + khóa sẽ bị xóa. Lưu ý rằng sp_reset_connection sẽ không hoặc không xóa chúng, mặc dù nó được quảng cáo là làm như vậy
Mảnh vụn từ phá thai này sẽ chặn các quá trình khác.
Cách để làm cho SQL Server xóa các giao dịch + khóa khi hết thời gian của máy khách (đúng, các sự kiện ABORT) là sử dụng SET XACT_ABORT ON.
Bạn có thể xác minh điều này đang mở 2 cửa sổ truy vấn trong SSMS:
Cửa sổ 1:
Trong menu Query..Query Options đặt thời gian chờ là 5 giây rồi chạy cái này
BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout
Cửa sổ 2, cái này sẽ đợi mãi (hoặc nhấn vào thời gian chờ của bạn)
SELECT * FROM sometable
SET XACT_ABORT ON cũng có tác dụng phụ thú vị:
- @@ TRANCOUNT được đặt thành 0 trên rollback ngầm nhưng lỗi 266 bị loại bỏ (điều này xảy ra nếu @@ TRANCOUNT khác với mục nhập và thoát khỏi một Proc được lưu trữ)
- XACT_STATE sẽ là -1 (đó là "cam chịu")
Sự kết hợp của điều này có nghĩa là bạn không thể sử dụng SAVEPOINTS (mặc dù, tôi không thể nhớ lại hành vi chính xác) cho các cam kết / rollback một phần. Phù hợp với tôi
Liên kết SO trên SET XACT_ABORT:
Trên các procs lưu trữ lồng nhau:
Trên sp_reset_connection: