Theo mặc định, hầu hết thời gian, Giao dịch không được tự động khôi phục / hủy khi xảy ra lỗi. Đây thường không phải là vấn đề miễn là bạn có cách xử lý lỗi thích hợp và ROLLBACK
tự gọi cho mình. Tuy nhiên, đôi khi mọi thứ trở nên phức tạp, chẳng hạn như trong trường hợp xảy ra lỗi hủy bỏ hàng loạt hoặc khi sử dụng OPENQUERY
(hoặc Máy chủ được liên kết nói chung) và xảy ra lỗi trên hệ thống từ xa. Mặc dù hầu hết các lỗi có thể bị mắc bẫy bằng cách sử dụng TRY...CATCH
, có hai lỗi không thể bị mắc kẹt theo cách đó (mặc dù không thể nhớ lỗi nào tại thời điểm này - nghiên cứu). Trong những trường hợp này, bạn phải sử dụng SET XACT_ABORT ON
để khôi phục đúng Giao dịch.
SET XACT_ABORT ON khiến SQL Server lập tức quay lại bất kỳ Giao dịch nào (nếu một giao dịch đang hoạt động) và hủy bỏ lô nếu có lỗi xảy ra. Cài đặt này tồn tại trước SQL Server 2005, đã giới thiệu TRY...CATCH
cấu trúc. Đối với hầu hết các phần, TRY...CATCH
xử lý hầu hết các tình huống và do đó chủ yếu là lỗi thời XACT_ABORT ON
. Tuy nhiên, khi sử dụng OPENQUERY
(và có thể là một kịch bản khác mà tôi không thể nhớ vào lúc này), thì bạn vẫn sẽ cần sử dụng SET XACT_ABORT ON;
.
Bạn phải luôn có cách xử lý lỗi thích hợp, đặc biệt là khi sử dụng Giao dịch. Cấu TRY...CATCH
trúc, được giới thiệu trong SQL Server 2005, cung cấp một phương thức xử lý gần như tất cả các tình huống, một cải tiến đáng hoan nghênh so với thử nghiệm @@ERROR
sau mỗi câu lệnh, điều này không giúp ích nhiều cho các lỗi hủy bỏ hàng loạt.
TRY...CATCH
giới thiệu một "trạng thái" mới, tuy nhiên. Khi không sử dụng TRY...CATCH
cấu trúc, nếu bạn có Giao dịch đang hoạt động và xảy ra lỗi, thì có một số đường dẫn có thể được thực hiện:
XACT_ABORT OFF
và lỗi hủy bỏ câu lệnh: Giao dịch vẫn hoạt động và quá trình xử lý tiếp tục với câu lệnh tiếp theo , nếu có.
XACT_ABORT OFF
và hầu hết các lỗi hủy bỏ hàng loạt: Giao dịch vẫn hoạt động và quá trình xử lý tiếp tục với đợt tiếp theo , nếu có.
XACT_ABORT OFF
và một số lỗi hủy bỏ hàng loạt nhất định: Giao dịch được khôi phục và xử lý tiếp tục với đợt tiếp theo , nếu có.
XACT_ABORT ON
và bất kỳ lỗi nào : Giao dịch được khôi phục và xử lý tiếp tục với đợt tiếp theo , nếu có.
TUY NHIÊN, khi sử dụng TRY...CATCH
, các lỗi hủy bỏ hàng loạt không hủy bỏ lô mà thay vào đó chuyển điều khiển sang CATCH
khối. Khi XACT_ABORT
là OFF
, các giao dịch vẫn sẽ là hoạt động đại đa số thời điểm đó, và bạn sẽ cần phải COMMIT
, hoặc có khả năng nhất, ROLLBACK
. Nhưng khi gặp phải một số lỗi hàng loạt hủy (chẳng hạn như với OPENQUERY
), hoặc khi XACT_ABORT
là ON
, các giao dịch sẽ được trong một trạng thái mới, "uncommitable". Ở trạng thái này, bạn không thể COMMIT
, bạn cũng không thể thực hiện bất kỳ hoạt động DML nào. Tất cả những gì bạn có thể làm là ROLLBACK
và SELECT
tuyên bố. Tuy nhiên, trong trạng thái "không thể khắc phục" này, Giao dịch đã được khôi phục khi xảy ra lỗi và việc ban hành ROLLBACK
chỉ là một hình thức, nhưng phải thực hiện.
Một hàm, XACT_STATE , có thể được sử dụng để xác định xem Giao dịch có hoạt động, không có tác dụng hay không tồn tại. Nên kiểm tra (ít nhất là một số, ít nhất) để kiểm tra chức năng này trong CATCH
khối để xác định xem kết quả có -1
(nghĩa là không có ích) thay vì kiểm tra nếu @@TRANCOUNT > 0
. Nhưng với XACT_ABORT ON
, đó phải là trạng thái duy nhất có thể tồn tại, vì vậy có vẻ như việc kiểm tra @@TRANCOUNT > 0
và XACT_STATE() <> 0
tương đương. Mặt khác, khi XACT_ABORT
là OFF
và có một giao dịch tích cực, sau đó nó có thể có tình trạng một trong hai 1
hoặc -1
trong CATCH
khối, cho phép khả năng phát hành COMMIT
thay vì ROLLBACK
(mặc dù, tôi không thể nghĩ ra một trường hợp khi một người nào đó muốnCOMMIT
nếu Giao dịch được cam kết). Có thể tìm thấy thêm thông tin và nghiên cứu về việc sử dụng XACT_STATE()
trong một CATCH
khối với XACT_ABORT ON
câu trả lời của tôi cho câu hỏi DBA.SE sau: Trong trường hợp nào giao dịch có thể được thực hiện từ bên trong khối CATCH khi XACT_ABORT được đặt thành BẬT? . Xin lưu ý rằng có một lỗi nhỏ XACT_STATE()
khiến nó trả về sai 1
trong một số trường hợp nhất định: XACT_STATE () trả về 1 khi được sử dụng trong CHỌN với một số biến hệ thống nhưng không có mệnh đề TỪ
spNewBilling3
ném lỗi, nhưng bạn không muốn quay lạispNewBilling2
hoặcspNewBilling1
sau đó chỉ cần xóa[begin|rollback|commit] transaction createSavebillinginvoice
khỏispSavesomename
.