ธุรกรรมแยกระดับ SNAPSHOT กับ TRUNCATE?


10

ฉันหวังว่าจะมีใครบางคนแสดงความเข้าใจบางอย่างเกี่ยวกับพฤติกรรมนี้ซึ่งฉันไม่ได้คาดหวังเกี่ยวกับการแยก SNAPSHOT กับ TRUNCATE

ฐานข้อมูล: อนุญาตการแยก Snapshot = True; Is Snapshot On Read ที่ได้รับการยอมรับ = False

ขั้นตอนที่ 1 (แทนที่เนื้อหาของ table foo จาก SELECT ที่ซับซ้อนที่รันเป็นเวลานานด้วยการรวมจำนวนมาก):

BEGIN TRAN; 
TRUNCATE TABLE foo; 
INSERT INTO foo SELECT...; 
COMMIT;

ขั้นตอนที่ 2 (อ่านจากตาราง foo):

SET TRANSACTION ISOLATION LEVEL SNAPSHOT; 
SELECT * FROM foo;

หากโพรซีเดอร์ 1 กำลังรันในขณะที่โพรซีเดอร์ 2 ถูกเรียกใช้งานโพรซีเดอร์ 2 จะถูกระงับด้วย LCK_M_SCH_S รอ (ตาม sp_WhoIsActive) จนกระทั่งขั้นตอน 1 เสร็จสิ้น และเมื่อโพรซีเดอร์ 2 เสร็จสิ้นจะทำให้เกิดข้อยกเว้นนี้:

ธุรกรรมแยก Snapshot ล้มเหลวในฐานข้อมูล 'DatabaseName' เนื่องจากวัตถุที่เข้าถึงโดยคำสั่งนั้นได้รับการแก้ไขโดยคำสั่ง DDL ในธุรกรรมอื่นพร้อมกันนับตั้งแต่เริ่มต้นธุรกรรมนี้ ไม่ได้รับอนุญาตเนื่องจากข้อมูลเมตาไม่ได้เป็นเวอร์ชัน การอัปเดตพร้อมกันเป็นข้อมูลเมตาสามารถนำไปสู่ความไม่สอดคล้องกันหากผสมกับการแยกสแนปชอต

อย่างไรก็ตาม Microsoft ไม่ได้แสดงรายการ TRUNCATE เป็นคำสั่ง DDL ที่ไม่ได้รับอนุญาตภายใต้การแยก SNAPSHOT: http://msdn.microsoft.com/en-us/library/bb933783.aspx

เห็นได้ชัดว่าฉันไม่เข้าใจบางสิ่งบางอย่างอย่างถูกต้องเนื่องจากฉันคาดว่ากรณีที่ดีที่สุดของขั้นตอนที่ 2 จะส่งคืนข้อมูลที่ได้รับล่าสุดจากตารางก่อน TRUNCATE หรือกรณีที่เลวร้ายที่สุดของขั้นตอนที่ 1 จากนั้นส่งคืนเนื้อหาใหม่ของ โต๊ะ. คุณช่วยได้ไหม


คุณสามารถใช้ DELETE จาก foo แทนได้หรือไม่ ที่จะไม่วางล็อคคี
SqlACID

ลบออกจากเป็นวิธีที่ฉันกำลังแก้ไขนี้ ฉันสนใจด้วยเช่นกันว่าเพราะเหตุใดฉันจึงได้รับข้อผิดพลาด
Mark Freeman

คำตอบ:


19

รายการของ'DDL'การดำเนินการที่ระบุไว้ไม่ครอบคลุม (และTRUNCATE TABLEไม่ได้เป็นการละเว้นเฉพาะจากรายการนั้น) ไม่ว่าจะTRUNCATE TABLEเป็นDMLหรือDDLเป็นคำถามที่เต็มไปด้วย SQL Server พร้อมตัวอย่างโน้มน้าวใจทั้งสองด้านของการอภิปรายและรายการทั้งสองวิธีใน Books Online

จากมุมมองของทรานแซคชันการแยกสแน็ปช็อตการตัดทอนมีคุณภาพที่สำคัญของการSch-Mล็อกซึ่งจะอธิบายการบล็อก (เพราะRCSIและSIยังคงได้รับการSch-Sล็อค ) และยังทำให้เวอร์ชันข้อมูลเมตาภายใน (สำหรับเหตุผลภายใน *) ทำให้เกิดข้อผิดพลาด 3961

ดังนั้นพฤติกรรมที่คุณเห็นเป็นสิ่งที่คาดหวัง แต่ก็ไม่ได้บันทึกไว้อย่างดี

* การใช้ TRUNCATE TABLE ในปัจจุบันไม่ได้สร้างเวอร์ชันของแถว การชนรุ่นข้อมูลเมตาเป็นวิธีที่ง่ายที่สุดในการตรวจสอบพฤติกรรมที่ถูกต้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.