Sql-Server

交易隔離級別快照與截斷?

  • June 6, 2014

我希望有人能對這種我沒有預料到的關於 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 的目前實現不生成行版本。碰撞元數據版本是確保正確行為的最簡單方法。

引用自:https://dba.stackexchange.com/questions/66683