Secara default, sebagian besar waktu Transaksi tidak dibatalkan / dibatalkan secara otomatis saat terjadi kesalahan. Ini biasanya bukan masalah selama Anda memiliki penanganan kesalahan yang tepat dan menelepon ROLLBACK
diri sendiri. Namun, kadang-kadang hal menjadi rumit, seperti dalam kasus kesalahan batch-dibatalkan, atau ketika menggunakan OPENQUERY
(atau Server Terkait pada umumnya) dan kesalahan terjadi pada sistem jarak jauh. Sementara sebagian besar kesalahan dapat terjebak menggunakan TRY...CATCH
, ada dua yang tidak bisa dijebak seperti itu (tidak bisa mengingat yang mana pada saat ini - meneliti). Dalam kasus ini, Anda harus menggunakan SET XACT_ABORT ON
untuk mengembalikan transaksi dengan benar.
SET XACT_ABORT ON menyebabkan SQL Server segera memutar kembali segala Transaksi (jika ada yang aktif) dan membatalkan kumpulan jika ada kesalahan. Pengaturan ini ada sebelum SQL Server 2005, yang memperkenalkan TRY...CATCH
konstruk. Sebagian besar, TRY...CATCH
menangani sebagian besar situasi dan sebagian besar kebutuhan usang XACT_ABORT ON
. Namun, ketika menggunakan OPENQUERY
(dan mungkin satu skenario lain yang saya tidak ingat saat ini), maka Anda masih harus menggunakan SET XACT_ABORT ON;
.
Anda harus selalu memiliki penanganan kesalahan yang tepat, terutama saat menggunakan Transaksi. The TRY...CATCH
membangun, diperkenalkan pada SQL Server 2005, menyediakan sarana penanganan hampir semua situasi, menyambut perbaikan atas pengujian untuk @@ERROR
setelah setiap pernyataan, yang tidak membantu banyak dengan kesalahan batch-batal.
TRY...CATCH
memperkenalkan "negara" baru, namun. Ketika tidak menggunakan TRY...CATCH
konstruk, jika Anda memiliki Transaksi aktif dan terjadi kesalahan, maka ada beberapa jalur yang dapat diambil:
XACT_ABORT OFF
dan kesalahan pembatalan pernyataan: Transaksi masih aktif dan pemrosesan dilanjutkan dengan pernyataan berikutnya , jika ada.
XACT_ABORT OFF
dan sebagian besar kesalahan pembatalan bets: Transaksi masih aktif dan pemrosesan berlanjut dengan bets berikutnya , jika ada.
XACT_ABORT OFF
dan kesalahan pembatalan bets tertentu: Transaksi dibatalkan dan pemrosesan dilanjutkan dengan bets berikutnya , jika ada.
XACT_ABORT ON
dan kesalahan apa pun : Transaksi dibatalkan dan pemrosesan dilanjutkan dengan batch berikutnya , jika ada.
NAMUN, saat menggunakan TRY...CATCH
, kesalahan yang dibatalkan batch tidak membatalkan batch, tetapi alih-alih mentransfer kontrol ke CATCH
blok. Ketika XACT_ABORT
adalah OFF
, Transaksi akan tetap aktif sebagian besar waktu, dan Anda akan perlu COMMIT
, atau paling mungkin, ROLLBACK
. Tapi ketika menghadapi kesalahan batch-batal tertentu (seperti dengan OPENQUERY
), atau ketika XACT_ABORT
adalah ON
, Transaksi akan berada dalam keadaan baru, "uncommitable". Dalam keadaan ini Anda tidak bisa COMMIT
, Anda juga tidak bisa melakukan operasi DML. Semua dapat Anda lakukan adalah ROLLBACK
dan SELECT
pernyataan. Akan tetapi, dalam keadaan "tidak dapat diterima" ini, Transaksi dibatalkan karena kesalahan yang terjadi, dan mengeluarkannya ROLLBACK
hanyalah formalitas, tetapi harus dilakukan.
Fungsi, XACT_STATE , dapat digunakan untuk menentukan apakah suatu Transaksi aktif, tidak dikomunikasikan, atau tidak ada. Dianjurkan (oleh beberapa orang, setidaknya) untuk memeriksa fungsi ini di CATCH
blok untuk menentukan apakah hasilnya -1
(yaitu uncommitable) alih-alih menguji jika @@TRANCOUNT > 0
. Tetapi dengan XACT_ABORT ON
, itu harus menjadi satu-satunya keadaan yang memungkinkan untuk dilakukan, sehingga tampaknya pengujian untuk @@TRANCOUNT > 0
dan XACT_STATE() <> 0
setara. Di sisi lain, ketika XACT_ABORT
adalah OFF
dan ada transaksi aktif, maka ada kemungkinan untuk memiliki keadaan baik 1
atau -1
di CATCH
blok, yang memungkinkan untuk kemungkinan menerbitkan COMMIT
bukan ROLLBACK
(meskipun, saya tidak bisa memikirkan kasus ketika seseorang inginCOMMIT
jika Transaksi berkomitmen). Informasi dan penelitian lebih lanjut tentang penggunaan XACT_STATE()
dalam CATCH
blok XACT_ABORT ON
dapat ditemukan dalam jawaban saya untuk pertanyaan DBA.SE berikut: Dalam kasus apa transaksi dapat dilakukan dari dalam blok CATCH ketika XACT_ABORT disetel ke ON? . Harap perhatikan bahwa ada bug minor XACT_STATE()
yang menyebabkannya salah 1
dalam skenario tertentu: XACT_STATE () mengembalikan 1 ketika digunakan dalam SELECT dengan beberapa variabel sistem tetapi tanpa klausa FROM dari klausa
spNewBilling3
melempar kesalahan, tetapi Anda tidak ingin memutar kembalispNewBilling2
atauspNewBilling1
, kemudian hanya menghapus[begin|rollback|commit] transaction createSavebillinginvoice
darispSavesomename
.