Saya berharap seseorang dapat menjelaskan perilaku ini yang saya tidak harapkan tentang isolasi SNAPSHOT vs TRUNCATE.
Basis Data: Izinkan Isolasi Snapshot = Benar; Dibaca Dibidik, Snapshot Aktif = Salah.
Procedure1 (Mengganti konten table foo dari SELECT kompleks yang sudah berjalan lama dengan banyak gabungan):
BEGIN TRAN;
TRUNCATE TABLE foo;
INSERT INTO foo SELECT...;
COMMIT;
Prosedur2 (Dibaca dari tabel foo):
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
SELECT * FROM foo;
Jika Prosedure1 sedang berjalan ketika Prosedure2 dijalankan, Prosedure2 ditunda dengan menunggu LCK_M_SCH_S (sesuai dengan sp_WhoIsActive) hingga Procedure1 selesai. Dan ketika Prosedur2 selesai, itu menimbulkan pengecualian ini:
Transaksi isolasi snapshot gagal dalam database 'DatabaseName' karena objek yang diakses oleh pernyataan telah dimodifikasi oleh pernyataan DDL dalam transaksi bersamaan lainnya sejak awal transaksi ini. Itu tidak diizinkan karena metadata tidak diversi. Pembaruan bersamaan untuk metadata dapat menyebabkan inkonsistensi jika dicampur dengan isolasi snapshot.
Namun, Microsoft tidak mencantumkan TRUNCATE sebagai pernyataan DDL yang tidak diizinkan di bawah isolasi SNAPSHOT: http://msdn.microsoft.com/en-us/library/bb933783.aspx
Jelas saya tidak memahami sesuatu dengan benar, seperti yang saya harapkan kasus terbaik dari Prosedur 2 segera mengembalikan data yang paling baru dilakukan dari tabel sebelum TRUNCATE atau kasus terburuk yang ditahan oleh Procedure1 dan kemudian mengembalikan konten baru meja. Bisakah kamu menolong?
sumber
Jawaban:
Daftar
'DDL'
operasi yang tercantum tidak komprehensif (danTRUNCATE TABLE
bukan satu-satunya penghilangan dari daftar itu). ApakahTRUNCATE TABLE
iniDML
atauDDL
adalah pertanyaan penuh di SQL Server, dengan contoh-contoh persuasif di kedua sisi perdebatan, dan entri kedua cara di buku Online.Dari sudut pandang transaksi isolasi snapshot, truncate memiliki kualitas penting dari mengambil
Sch-M
kunci , yang menjelaskan pemblokiran (karenaRCSI
danSI
masih memperolehSch-S
kunci ); dan itu juga menabrak versi metadata internal (karena alasan internal *) mengakibatkan kesalahan 3961.Jadi, perilaku yang Anda lihat diharapkan, tidak didokumentasikan dengan baik.
* Implementasi TRUNCATE TABLE saat ini tidak menghasilkan versi baris. Membenturkan versi metadata adalah cara paling sederhana untuk memastikan perilaku yang benar.
sumber