交易隔離級別快照與截斷?
我希望有人能對這種我沒有預料到的關於 SNAPSHOT 隔離與 TRUNCATE 的行為有所了解。
數據庫:允許快照隔離 = True;是否已送出讀取快照打開 = False。
過程 1(用大量連接替換長時間執行的複雜 SELECT 表 foo 的內容):
BEGIN TRAN; TRUNCATE TABLE foo; INSERT INTO foo SELECT...; COMMIT;
程序 2(從表 foo 中讀取):
SET TRANSACTION ISOLATION LEVEL SNAPSHOT; SELECT * FROM foo;
如果在執行 Procedure2 時 Procedure1 正在執行,則 Procedure2 將等待 LCK_M_SCH_S 等待(根據 sp_WhoIsActive),直到 Procedure1 完成。當 Procedure2 完成時,它會引發此異常:
數據庫“DatabaseName”中的快照隔離事務失敗,因為自該事務開始以來,該語句訪問的對像已被另一個並發事務中的 DDL 語句修改。這是不允許的,因為元數據沒有版本化。如果與快照隔離混合,對元數據的並發更新可能會導致不一致。
但是,Microsoft 並未將 TRUNCATE 列為 SNAPSHOT 隔離下不允許的 DDL 語句:http: //msdn.microsoft.com/en-us/library/bb933783.aspx
顯然我沒有正確理解某些東西,因為我本以為 Procedure2 的最佳情況會在 TRUNCATE 之前立即從表中返回最近送出的數據,或者最壞的情況是被 Procedure1 阻止,然後返回新的內容桌子。你能幫我嗎?
列出的
'DDL'
操作列表並不全面(並且TRUNCATE TABLE
不是該列表中唯一的遺漏)。SQL Server中是否TRUNCATE TABLE
是一個令人擔憂的問題,辯論雙方都有有說服力的範例,並且在聯機叢書中有兩種方式的條目。DML``DDL
從快照隔離事務的角度來看,truncate 具有取
Sch-M
鎖的本質特性,這解釋了阻塞(因為RCSI
並且SI
仍然獲取Sch-S
鎖);它還會影響內部元數據版本(出於內部原因*),導致錯誤 3961。因此,您看到的行為是預期的,只是沒有很好地記錄。
- TRUNCATE TABLE 的目前實現不生成行版本。碰撞元數據版本是確保正確行為的最簡單方法。