Giao dịch và thử bắt trong SQL Server Job


9

Chúng tôi có các hoạt động DML trong từng bước của công việc Máy chủ SQL. Để đảm bảo cập nhật / chèn sẽ được khôi phục trong trường hợp xảy ra sự cố, tôi đã gói các sửa đổi dữ liệu của từng bước trong TRY CATCHTRANSACTIONchặn:

BEGIN TRY
    BEGIN TRANSACTION

        [[INSERT/update statements]] ...

    IF @@TRANCOUNT > 0
    BEGIN
        COMMIT TRANSACTION
        PRINT 'Successful.'
    END

END TRY

BEGIN CATCH
    SELECT
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage

    IF @@TRANCOUNT > 0
    BEGIN
        ROLLBACK TRANSACTION
        PRINT 'Unsuccessful.'
    END
END CATCH

Nó có đảm bảo các thao tác dữ liệu sẽ được khôi phục trong trường hợp có lỗi không? Hoặc những cân nhắc khác nên được đưa vào tài khoản?

Sẽ có cách nào tốt hơn để làm điều đó (sử dụng cấu hình, vv)?

Cảm ơn bạn.

Câu trả lời:


7

Tôi muốn đề xuất một mẫu giống như mẫu từ 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

Mẫu này kiểm tra XACT_STATE()khối bắt để bảo vệ chống lại các giao dịch không đáng có :

Giao dịch không thể chấp nhận và XACT_STATE
Nếu một lỗi được tạo trong khối TRY làm cho trạng thái của giao dịch hiện tại bị vô hiệu, giao dịch được phân loại là một giao dịch không thể chấp nhận được. Một lỗi thông thường kết thúc một giao dịch bên ngoài khối TRY khiến giao dịch đi vào trạng thái không thể khắc phục khi lỗi xảy ra bên trong khối TRY. Một giao dịch không thể chấp nhận chỉ có thể thực hiện các hoạt động đọc hoặc GIAO DỊCH ROLLBACK. Giao dịch không thể thực thi bất kỳ câu lệnh Transact-SQL nào sẽ tạo ra thao tác ghi hoặc GIAO DỊCH GIAO DỊCH. Hàm XACT_STATE trả về giá trị -1 nếu giao dịch đã được phân loại là giao dịch không thể chấp nhận được. Khi một đợt kết thúc, Cơ sở dữ liệu sẽ khôi phục mọi giao dịch không hoạt động. Nếu không có thông báo lỗi được gửi khi giao dịch vào trạng thái không thể kiểm soát được, khi lô kết thúc, một thông báo lỗi sẽ được gửi đến ứng dụng khách. Điều này chỉ ra rằng một giao dịch không đáng có đã được phát hiện và khôi phục.

Mã của bạn đang kiểm tra @@TRANCOUNTở những nơi không thể bằng 0, nó sử dụng hỗn hợp các thông báo PRINT thông tin và bộ kết quả CHỌN để truyền đạt thành công, nó không xử lý các lỗi có thể phục hồi. Lý tưởng nhất là các ngoại lệ nên truyền tới khách hàng, trong trường hợp này là công việc Đại lý (nghĩa là sản lượng khai thác của bạn sẽ được nâng lên lại).


Cảm ơn câu trả lời hữu ích của bạn và trang web tuyệt vời! Tuy nhiên, tôi tự hỏi liệu tôi vẫn có thể sử dụng mẫu này với một câu lệnh DML đơn giản (không phải là một Proc được lưu trữ) không? Ngoài ra chúng ta có phải lưu giao dịch như dưới đây không? (Tôi không có một cửa hàng Proc để sử dụng): lưu giao dịch usp_my_procedure_name;
Bầu trời

2

Những gì bạn có vẻ tốt với tôi. Tôi sẽ đề nghị làm một cái gì đó với thông tin tất nhiên sau khi bạn đã khôi phục giao dịch, ví dụ như viết nó ra một bản ghi.


1
Cảm ơn câu trả lời của bạn, bạn có thể vui lòng cho tôi một gợi ý làm thế nào để viết nó vào một bản ghi?
Bầu trời

3
Nếu bạn muốn ghi lỗi hoặc dữ liệu vào bảng nhật ký, thì trước khi bạn thực hiện khôi phục, hãy sao chép dữ liệu bạn muốn vào biến bảng (Điều quan trọng là bạn sử dụng biến bảng, bảng tạm thời sẽ được khôi phục.) rollback, sau đó chèn dữ liệu từ biến bảng vào bảng ghi nhật ký.
HLGEM
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.