Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Kesalahan Pemicu:Transaksi saat ini tidak dapat dilakukan dan tidak dapat mendukung operasi yang menulis ke file log

Kesalahan ini terjadi ketika Anda menggunakan blok coba/tangkap di dalam transaksi. Mari kita pertimbangkan contoh sepele:

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

Ketika penyisipan keempat menyebabkan kesalahan, kumpulan dihentikan dan transaksi dibatalkan. Tidak ada kejutan sejauh ini.

Sekarang mari kita coba menangani kesalahan itu dengan blok 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

Kami menangkap kesalahan kunci duplikat, tetapi sebaliknya, kami tidak lebih baik. Batch kami masih dihentikan, dan transaksi kami masih dibatalkan. Alasannya sebenarnya sangat sederhana:

Pencekalan TRY/CATCH tidak memengaruhi transaksi.

Karena XACT_ABORT AKTIF, saat terjadi kesalahan kunci duplikat, transaksi akan gagal. Ini dilakukan untuk. Sudah terluka parah. Itu telah ditembakkan ke jantung... dan kesalahan yang harus disalahkan. TRY/CATCH memberikan SQL Server...nama yang buruk. (maaf, tidak bisa menolak)

Dengan kata lain, itu akan TIDAK PERNAH berkomitmen dan akan SELALU digulung kembali. Yang bisa dilakukan blok TRY/CATCH hanyalah mematahkan jatuhnya mayat. Kita dapat menggunakan XACT_STATE() berfungsi untuk melihat apakah transaksi kita dapat dikomit. Jika tidak, satu-satunya pilihan adalah membatalkan transaksi.

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

Pemicu selalu dieksekusi dalam konteks transaksi, jadi jika Anda dapat menghindari menggunakan TRY/CATCH di dalamnya, segalanya jauh lebih sederhana.

Untuk solusi masalah Anda, CLR Stored Proc dapat terhubung kembali ke SQL Server dalam koneksi terpisah untuk menjalankan SQL dinamis. Anda mendapatkan kemampuan untuk mengeksekusi kode dalam transaksi baru dan logika penanganan kesalahan mudah ditulis dan mudah dipahami dalam 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. Buat Tabel Temp dengan Rentang Angka

  2. Secara otomatis menyelesaikan konflik penggabungan kunci utama

  3. Beberapa Koneksi Dengan String Koneksi Yang Sama Dalam Satu Transaksi, Transaksi Ditingkatkan?

  4. Tampilan SQL Penjualan Tanggal Paralel

  5. Mendapatkan hasil prosedur tersimpan SQL ke dalam format data.frame menggunakan RODBC