Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Lỗi kích hoạt:Giao dịch hiện tại không thể được cam kết và không thể hỗ trợ các hoạt động ghi vào tệp nhật ký

Lỗi này xảy ra khi bạn sử dụng khối try / catch bên trong giao dịch. Hãy xem xét một ví dụ nhỏ:

SET XACT_ABORT ON

IF object_id('tempdb..#t') IS NOT NULL
    DROP TABLE #t
CREATE TABLE #t (i INT NOT NULL PRIMARY KEY)

BEGIN TRAN
    INSERT INTO #t (i) VALUES (1)
    INSERT INTO #t (i) VALUES (2)
    INSERT INTO #t (i) VALUES (3)
    INSERT INTO #t (i) VALUES (1) -- dup key error, XACT_ABORT kills the batch
    INSERT INTO #t (i) VALUES (4) 

COMMIT  TRAN
SELECT * FROM #t

Khi lần chèn thứ tư gây ra lỗi, lô sẽ bị chấm dứt và giao dịch quay trở lại. Không có bất ngờ cho đến nay.

Bây giờ, hãy cố gắng xử lý lỗi đó bằng khối TRY / CATCH:

SET XACT_ABORT ON
IF object_id('tempdb..#t') IS NOT NULL
    DROP TABLE #t
CREATE TABLE #t (i INT NOT NULL PRIMARY KEY)

BEGIN TRAN
    INSERT INTO #t (i) VALUES (1)
    INSERT INTO #t (i) VALUES (2)
    BEGIN TRY
        INSERT INTO #t (i) VALUES (3)
        INSERT INTO #t (i) VALUES (1) -- dup key error
    END TRY
    BEGIN CATCH
        SELECT ERROR_MESSAGE()
    END CATCH  
    INSERT INTO #t (i) VALUES (4)
    /* Error the Current Transaction cannot be committed and 
    cannot support operations that write to the log file. Roll back the transaction. */

COMMIT TRAN
SELECT * FROM #t

Chúng tôi đã gặp lỗi khóa trùng lặp, nhưng nếu không, chúng tôi không khá hơn. Lô của chúng tôi vẫn bị chấm dứt và giao dịch của chúng tôi vẫn được khôi phục. Lý do thực sự rất đơn giản:

Các khối TRY / CATCH không ảnh hưởng đến giao dịch.

Do việc BẬT XACT_ABORT, thời điểm xảy ra lỗi khóa trùng lặp, giao dịch sẽ bị hủy. Nó được thực hiện cho. Nó đã bị thương nặng. Nó bị bắn xuyên tim ... và có lỗi. TRY / CATCH mang lại cho SQL Server ... một cái tên tồi. (xin lỗi, không thể chống lại)

Nói cách khác, nó sẽ KHÔNG BAO GIỜ cam kết và sẽ LUÔN LUÔN được cuộn lại. Tất cả những gì khối TRY / CATCH có thể làm là phá vỡ sự rơi của xác chết. Chúng tôi có thể sử dụng XACT_STATE () chức năng để xem liệu giao dịch của chúng tôi có được cam kết hay không. Nếu không, lựa chọn duy nhất là quay trở lại giao dịch.

SET XACT_ABORT ON -- Try with it OFF as well.
IF object_id('tempdb..#t') IS NOT NULL
    DROP TABLE #t
CREATE TABLE #t (i INT NOT NULL PRIMARY KEY)

BEGIN TRAN
    INSERT INTO #t (i) VALUES (1)
    INSERT INTO #t (i) VALUES (2)

    SAVE TRANSACTION Save1
    BEGIN TRY
        INSERT INTO #t (i) VALUES (3)
        INSERT INTO #t (i) VALUES (1) -- dup key error
    END TRY
    BEGIN CATCH
        SELECT ERROR_MESSAGE()
        IF XACT_STATE() = -1 -- Transaction is doomed, Rollback everything.
            ROLLBACK TRAN
        IF XACT_STATE() = 1 --Transaction is commitable, we can rollback to a save point
            ROLLBACK TRAN Save1
    END CATCH  
    INSERT INTO #t (i) VALUES (4)

IF @@TRANCOUNT > 0
    COMMIT TRAN
SELECT * FROM #t

Các trình kích hoạt luôn thực hiện trong ngữ cảnh của một giao dịch, vì vậy nếu bạn có thể tránh sử dụng TRY / CATCH bên trong chúng, mọi thứ sẽ đơn giản hơn nhiều.

Để có giải pháp cho vấn đề của bạn, CLR Stored Proc có thể kết nối trở lại SQL Server trong một kết nối riêng biệt để thực thi SQL động. Bạn có khả năng thực thi mã trong một giao dịch mới và logic xử lý lỗi vừa dễ viết vừa dễ hiểu trong C #.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hàm DECODE () trong SQL Server

  2. DATETIMEOFFSETFROMPARTS () Ví dụ trong SQL Server (T-SQL)

  3. SQL Server, kết hợp LIKE và IN?

  4. sql varchar (tối đa) so với varchar (sửa chữa)

  5. Cú pháp kiểm tra tất cả các thủ tục được lưu trữ?