Hết thời gian giao dịch máy chủ SQL


9

Có cách nào trong SQL Server 2008 R2 để hết thời gian sửa đổi cơ sở dữ liệu liên quan đến giao dịch không? Chúng tôi có một kịch bản trong đó mã ứng dụng của chúng tôi bị treo hoặc ném ngoại lệ và không thực hiện khôi phục hoặc cam kết. Điều này sau đó khiến các phiên khác bị treo chờ giao dịch hoàn tất.

Câu trả lời:


20

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:


Tương lai nói xin chào! "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à như vậy" - Tôi không tin điều này còn đúng trong các phiên bản cập nhật của SQL Server?
kamilk

11

Tôi đang trả lời điều này với sự do dự vì không có đủ thông tin trong mô tả vấn đề của bạn để chắc chắn 100% đây là lời khuyên tốt nhất. "Treo hoặc ném một ngoại lệ" cho thấy nguồn gốc của vấn đề không được hiểu đúng, vì vậy hãy thận trọng.

Giải pháp đơn giản nhất cho điều này có lẽ là SET XACT_ABORT ON.

XACT_ABORTxác định xem SQL Server có phục hồi giao dịch trong trường hợp xảy ra lỗi trong thời gian chạy hay không. Mặc định SET XACT_ABORT OFFsẽ chỉ khôi phục lại câu lệnh gây ra lỗi, để lại bất kỳ giao dịch mẹ nào mở.

Hiệu ứng phụ "gotcha" của cài đặt mặc định là thời gian chờ có thể gây ra chính xác cùng một vấn đề, một giao dịch mở là trách nhiệm của khách hàng để xử lý và khôi phục. Nếu khách hàng không thử / bắt / quay lại, giao dịch sẽ vẫn mở cho đến khi tham dự với (và tôi trích dẫn @gbn) mức độ cực kỳ bạo lực của KILL <spid>.

Tt trích dẫn các bài viết của Erland Sommarskog về xử lý lỗi trong SQL Server chứa tất cả nền tảng và chiến lược bạn cần để xử lý các tình huống này và hơn thế nữa.

Chỉnh sửa (nhận xét sau): Để xác định các giao dịch mở, sp_whoisactive có lẽ là tính năng hoàn chỉnh nhất.


Tôi đã tìm thấy, với một số Googling, các cách để tìm các giao dịch mở khi treo xảy ra - có thể đây là giải pháp tốt nhất. Đó là tìm ra nguyên nhân gây ra giao dịch không được tiết lộ trong mã và khắc phục các lỗ hổng trong mã. Để tham khảo cho người khác. DBCC OPENTRAN trả về giao dịch hoạt động lâu đời nhất -> msdn.microsoft.com/en-us/l Library / ms182792.aspx Hoặc một cái gì đó giống như thế này? -> weblogs.sqlteam.com/mladenp/archive/2008/04/29/ Kẻ
David Gray Wright

Tôi đã luôn nghĩ Erland đã không làm công lý cho SET XACT_ABORT sommarskog.se/error-handling-I.html#XACT_ABORT
gbn
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.