2009-11-17 19 views
141

Chúng tôi có ứng dụng client đang chạy một số lệnh SQL trên SQL Server 2005 như sau:Máy chủ SQL - các giao dịch quay trở lại do lỗi?

BEGIN TRAN; 
INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
COMMIT TRAN; 

Nó được gửi bởi một lệnh chuỗi dài.

Nếu một trong các chèn không thành công hoặc bất kỳ phần nào của lệnh không thành công, SQL Server có quay lại giao dịch không? Nếu nó không rollback, tôi có phải gửi một lệnh thứ hai để cuộn nó trở lại?

Tôi có thể cung cấp chi tiết cụ thể về api và ngôn ngữ tôi đang sử dụng, nhưng tôi nghĩ SQL Server sẽ phản hồi như nhau đối với bất kỳ ngôn ngữ nào.

+0

http://stackoverflow.com/questions/1150032/what-is-the-benefit-of-using-set- xact-abort-on-in-a-lưu trữ-thủ tục – zloctb

Trả lời

157

Bạn có thể đặt set xact_abort on trước khi giao dịch của bạn để đảm bảo cuộn sql lại tự động trong trường hợp lỗi.

+1

Điều này có hoạt động trên MS SQL 2K trở lên không? Điều này có vẻ là giải pháp đơn giản nhất. – jonathanpeppers

+1

Nó xuất hiện trong các tài liệu cho năm 2000, 2005 và 2008 vì vậy tôi giả sử có. Chúng tôi đang sử dụng nó trong năm 2008. – DyingCactus

+0

Có tùy chọn nào để khôi phục thời gian chờ mạng hoặc lỗi mạng nói chung không? Hoặc tùy chọn này xử lý tất cả trong một? – jonathanpeppers

10

Nếu một trong các chèn không thành công hoặc bất kỳ phần nào của lệnh không thành công, máy chủ SQL có quay lại giao dịch không?

Không, không.

Nếu nó không khôi phục, tôi có phải gửi lệnh thứ hai để cuộn lại không?

Chắc chắn, bạn nên phát hành ROLLBACK thay vì COMMIT.

Nếu bạn muốn quyết định xem có nên cam kết hoặc rollback giao dịch, bạn nên loại bỏ các COMMIT câu ra khỏi báo cáo kết quả, kiểm tra kết quả của chèn và sau đó phát hành một trong hai COMMIT hoặc ROLLBACK tùy thuộc vào kết quả của cuộc kiểm tra.

+0

Vì vậy, nếu tôi nhận được một lỗi, nói "chính xung đột chính" Tôi cần phải gửi một cuộc gọi thứ hai để rollback?Tôi đoán nó có lý. Điều gì xảy ra nếu có một lỗi liên quan đến mạng chẳng hạn như kết nối bị ngắt trong một câu lệnh SQL đang chạy rất dài? – jonathanpeppers

+2

Khi kết nối hết thời gian, giao thức mạng cơ bản (e. G. 'Đặt tên Pipes' hoặc' TCP') ngắt kết nối. Khi một kết nối bị hỏng, 'SQL Server' dừng tất cả các lệnh đang chạy và quay trở lại giao dịch. – Quassnoi

+1

Vì vậy, giải pháp của DyingCactus có vẻ như nó sửa lỗi của tôi, nhờ sự giúp đỡ. – jonathanpeppers

154

Bạn chính xác trong đó toàn bộ giao dịch sẽ được khôi phục. Bạn nên ra lệnh để cuộn nó trở lại.

Bạn có thể quấn này trong một khối TRY CATCH như sau

BEGIN TRY 
    BEGIN TRANSACTION 

     INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
     INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
     INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 

    COMMIT TRAN -- Transaction Success! 
END TRY 
BEGIN CATCH 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRAN --RollBack in case of Error 

    -- you can Raise ERROR with RAISEERROR() Statement including the details of the exception 
    RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1) 
END CATCH 
+1

Tôi thích giải pháp của DyingCactus tốt hơn, anh ấy là 1 dòng mã để thay đổi. Nếu của bạn nếu vì lý do nào đó tốt hơn (hoặc đáng tin cậy hơn) cho tôi biết. – jonathanpeppers

+9

Các thử bắt cung cấp cho bạn khả năng nắm bắt (và có thể sửa chữa) các lỗi và nâng cao một thông báo lỗi tùy chỉnh nếu cần thiết. –

+0

Vì chúng ta không thực sự quan tâm đến việc xử lý lỗi cụ thể trong SQL, tôi nghĩ chúng ta sẽ làm việc với giải pháp của DyingCactus. – jonathanpeppers

15

Từ bài viết MDSN, Controlling Transactions (Database Engine).

Nếu lỗi báo cáo thời gian chạy (ví dụ như vi phạm ràng buộc) xảy ra theo lô, hành vi mặc định trong Công cụ cơ sở dữ liệu là chỉ quay lại câu lệnh đã tạo lỗi. Bạn có thể thay đổi hành vi này bằng cách sử dụng câu lệnh SET XACT_ABORT. Sau khi SET XACT_ABORT ON được thực hiện, bất kỳ lỗi báo cáo thời gian chạy nào cũng gây ra một sự hồi phục tự động của giao dịch hiện tại. Biên dịch lỗi, chẳng hạn như lỗi cú pháp, không bị ảnh hưởng bởi SET XACT_ABORT. Để biết thêm thông tin, xem SET XACT_ABORT (Transact-SQL).

Trong trường hợp của bạn, nó sẽ hoàn nguyên giao dịch hoàn chỉnh khi bất kỳ lần chèn nào không thành công.

+1

chúng ta cần xử lý các lỗi cú pháp là gì? hoặc biên dịch lỗi? nếu bất kỳ ai trong số họ xảy ra toàn bộ giao dịch nên được khôi phục – MonsterMMORPG

7

Đây mã với nhận được thông báo lỗi làm việc với MSSQL Server 2016:

BEGIN TRY 
    BEGIN TRANSACTION 
     -- Do your stuff that might fail here 
    COMMIT 
END TRY 
BEGIN CATCH 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRAN 

     DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE() 
     DECLARE @ErrorSeverity INT = ERROR_SEVERITY() 
     DECLARE @ErrorState INT = ERROR_STATE() 

    -- Use RAISERROR inside the CATCH block to return error 
    -- information about the original error that caused 
    -- execution to jump to the CATCH block. 
    RAISERROR (@ErrorMessage, -- Message text. 
       @ErrorSeverity, -- Severity. 
       @ErrorState -- State. 
       ); 
END CATCH 
+1

Tôi đã phải sử dụng 'DECLARE @Var TYPE; SET @Var = ERROR; 'để tăng lỗi trong máy chủ sql 2005. Nếu không mã trên để tăng lỗi hoạt động cho DB cũ hơn. Việc cố gán giá trị mặc định cho biến cục bộ là điều đang gây ra sự cố. – jtlindsey

Các vấn đề liên quan