Lợi ích của việc sử dụng LẬP TỨC XACT_ABORT TRÊN NỀN TẢNG trong một thủ tục được lưu trữ là gì?


Câu trả lời:


231

SET XACT_ABORT ONhướng dẫn SQL Server khôi phục lại toàn bộ giao dịch và hủy bỏ đợt khi xảy ra lỗi trong thời gian chạy. Nó bao gồm bạn trong các trường hợp như thời gian chờ lệnh xảy ra trên ứng dụng khách thay vì trong chính SQL Server (không được bao phủ trong XACT_ABORT OFFcài đặt mặc định .)

Vì thời gian chờ truy vấn sẽ khiến giao dịch mở, SET XACT_ABORT ONnên được khuyến nghị trong tất cả các quy trình được lưu trữ với các giao dịch rõ ràng (trừ khi bạn có lý do cụ thể để làm khác) vì hậu quả của một ứng dụng thực hiện công việc trên kết nối với giao dịch mở là thảm họa.

Có một cái nhìn tổng quan thực sự tuyệt vời trên Blog của Dan Guzman ,


41
vậy tại sao nó không BẬT theo mặc định?
Mike W

1
XACT_ABORT vẫn được yêu cầu nếu bạn có BEGIN TRY- BEGIN CATCHROLLBACKvới BEGIN CATCHkhối trong Sql?
dùng2058

1
@ user20353 BEGIN TRY- BEGIN CATCHsẽ không bắt gặp những thứ như thời gian chờ xảy ra trên ứng dụng khách và một số lỗi SQL cũng không thể khắc phục được, khiến bạn có một giao dịch mở mà bạn không mong đợi.
Tom Lint

37

Theo tôi, SET XACT_ABORT ON đã bị lỗi thời khi bổ sung BEGIN TRY / BEGIN CATCH trong SQL 2k5. Trước các khối ngoại lệ trong Transact-SQL, thực sự rất khó để xử lý lỗi và các quy trình không cân bằng đều quá phổ biến (các quy trình có @@ TRANCOUNT khác khi thoát so với mục nhập).

Với việc bổ sung xử lý ngoại lệ Transact-SQL sẽ dễ dàng hơn nhiều để viết các quy trình chính xác được đảm bảo để cân bằng chính xác các giao dịch. Chẳng hạn, tôi sử dụng mẫu này để xử lý ngoại lệ và giao dịch lồng nhau :

create procedure [usp_my_procedure_name]
as
begin
    set nocount on;
    declare @trancount int;
    set @trancount = @@trancount;
    begin try
        if @trancount = 0
            begin transaction
        else
            save transaction usp_my_procedure_name;

        -- Do the actual work here

lbexit:
        if @trancount = 0   
            commit;
    end try
    begin catch
        declare @error int, @message varchar(4000), @xstate int;
        select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
        if @xstate = -1
            rollback;
        if @xstate = 1 and @trancount = 0
            rollback
        if @xstate = 1 and @trancount > 0
            rollback transaction usp_my_procedure_name;

        raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
    end catch   
end
go

Nó cho phép tôi viết các thủ tục nguyên tử chỉ quay lại công việc của chính họ trong trường hợp có lỗi có thể phục hồi.

Một trong những vấn đề chính mà các thủ tục Transact-SQL phải đối mặt là độ tinh khiết của dữ liệu : đôi khi các tham số nhận được hoặc dữ liệu trong các bảng chỉ đơn giản là sai, dẫn đến lỗi khóa trùng lặp, lỗi ràng buộc tham chiếu, kiểm tra lỗi ràng buộc, v.v. Xét cho cùng, đó chính xác là vai trò của các ràng buộc này, nếu các lỗi về độ tinh khiết dữ liệu này là không thể và tất cả bị logic kinh doanh nắm bắt, các ràng buộc đó sẽ bị lỗi thời (cường điệu hóa thêm vào có hiệu lực). Nếu XACT_ABORT BẬT thì tất cả các lỗi này dẫn đến toàn bộ giao dịch bị mất, trái ngược với việc có thể mã hóa các khối ngoại lệ xử lý ngoại lệ một cách duyên dáng. Một ví dụ điển hình là cố gắng thực hiện một CHERTN và trở lại CẬP NHẬT về vi phạm PK.


9
Ngoại trừ thời gian chờ của khách hàng ... và quan điểm của tôi là SET XACT_ABORT hiệu quả hơn trong SQL 2005 vì hành vi có thể dự đoán được nhiều hơn: lỗi hủy bỏ hàng loạt ít hơn rất nhiều.
gbn

7
Tôi đồng ý phần nào, nhưng tôi có kế hoạch xử lý lỗi của mình xung quanh tất cả các tình huống, bởi vì tôi biết tôi sẽ bị đổ lỗi là Nhà phát triển DBA nếu xảy ra thời gian chờ lệnh.
gbn

4
@RemusRusanu Làm thế nào khác bạn sẽ xử lý một hoạt động cơ sở dữ liệu đồng bộ, chạy dài?
Ian Boyd

5
Tài liệu MSDN nêu rõ: "XACT_ABORT phải được đặt BẬT cho các câu lệnh sửa đổi dữ liệu trong một giao dịch ngầm hoặc rõ ràng đối với hầu hết các nhà cung cấp OLE DB, bao gồm cả SQL Server. Trường hợp duy nhất không bắt buộc tùy chọn này là nếu nhà cung cấp hỗ trợ các giao dịch lồng nhau." msdn.microsoft.com/en-us/l Library / ms188792 (v = sql.120) .aspx
Nathan

4
"Theo ý kiến ​​của tôi, SET XACT_ABORT ON đã trở nên lỗi thời khi bổ sung BEGIN TRY / BEGIN CATCH" - Tôi nghe thấy bạn, nhưng vui lòng xem sommarskog.se/error_handling/Part1.html
Kỹ sư đảo ngược

22

Trích dẫn MSDN :

Khi SET XACT_ABORT BẬT, nếu câu lệnh Transact-SQL xuất hiện lỗi thời gian chạy, toàn bộ giao dịch bị chấm dứt và được khôi phục. Khi SET XACT_ABORT TẮT, trong một số trường hợp, chỉ có câu lệnh Transact-SQL gây ra lỗi được khôi phục và giao dịch tiếp tục xử lý.

Trong thực tế, điều này có nghĩa là một số câu lệnh có thể thất bại, khiến giao dịch 'hoàn thành một phần' và có thể không có dấu hiệu nào cho sự thất bại này đối với người gọi.

Một ví dụ đơn giản:

INSERT INTO t1 VALUES (1/0)    
INSERT INTO t2 VALUES (1/1)    
SELECT 'Everything is fine'

Mã này sẽ thực thi 'thành công' với XACT_ABORT OFF và sẽ chấm dứt với lỗi với XACT_ABORT ON ('INSERT INTO t2' sẽ không được thực thi và ứng dụng khách sẽ đưa ra một ngoại lệ).

Là một cách tiếp cận linh hoạt hơn, bạn có thể kiểm tra @@ ERROR sau mỗi câu lệnh (trường cũ) hoặc sử dụng các khối TRY ... CATCH (MSSQL2005 +). Cá nhân tôi thích đặt XACT_ABORT ON bất cứ khi nào không có lý do cho một số xử lý lỗi nâng cao.


8

Về thời gian chờ của khách hàng và việc sử dụng XACT_ABORT để xử lý chúng, theo tôi, có ít nhất một lý do rất chính đáng để có thời gian chờ trong các API khách như SqlClient và đó là để bảo vệ mã ứng dụng khách khỏi các bế tắc xảy ra trong mã máy chủ SQL. Trong trường hợp này, mã máy khách không có lỗi, nhưng phải tự bảo vệ nó khỏi bị chặn vĩnh viễn chờ lệnh hoàn thành trên máy chủ. Do đó, ngược lại, nếu thời gian chờ của máy khách phải tồn tại để bảo vệ mã máy khách, thì XACT_ABORT ON cũng phải bảo vệ mã máy chủ khỏi sự hủy bỏ của máy khách, trong trường hợp mã máy chủ mất nhiều thời gian để thực thi hơn là máy khách sẵn sàng chờ đợi.


1

Nó được sử dụng trong quản lý giao dịch để đảm bảo rằng bất kỳ lỗi nào dẫn đến giao dịch được khôi phục.

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.