Mar*_*man 10 sql-server sql-server-2008-r2 truncate snapshot-isolation
我希望有人可以对我没有预料到的关于 SNAPSHOT 隔离与 TRUNCATE 的这种行为有所了解。
数据库:允许快照隔离 = True;已读已提交快照 = False。
过程 1(用大量连接替换长期运行的复杂 SELECT 表 foo 的内容):
BEGIN TRAN;
TRUNCATE TABLE foo;
INSERT INTO foo SELECT...;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
程序 2(从表 foo 中读取):
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
SELECT * FROM foo;
Run Code Online (Sandbox Code Playgroud)
如果在执行程序 2 时程序 1 正在运行,程序 2 将通过 LCK_M_SCH_S 等待(根据 sp_WhoIsActive)暂停,直到程序 1 完成。当 Procedure2 完成时,它会引发此异常:
数据库“DatabaseName”中的快照隔离事务失败,因为自该事务开始以来,该语句访问的对象已被另一个并发事务中的 DDL 语句修改。这是不允许的,因为元数据没有版本化。如果与快照隔离混合使用,对元数据的并发更新可能会导致不一致。
但是,Microsoft 并未将 TRUNCATE 列为 SNAPSHOT 隔离下不允许的 DDL 语句:http : //msdn.microsoft.com/en-us/library/bb933783.aspx
显然,我没有正确理解某些东西,因为我本来期望 Procedure2 的最佳情况是在 TRUNCATE 之前立即从表中返回最近提交的数据,或者是被 Procedure1 阻止然后返回新内容的最坏情况桌子。你能帮我吗?
Pau*_*ite 19
列出的'DDL'操作列表并不全面(并且TRUNCATE TABLE不是该列表中唯一的遗漏)。无论TRUNCATE TABLE是DML或者DDL是SQL Server一个充满问题,对辩论双方有说服力的例子,和条目联机丛书中的两种方式。
从一个快照隔离交易的角度来看,具有截断的基本质量采取Sch-M锁,这解释了阻挡(因为RCSI和SI仍然获取Sch-S锁); 并且它还会碰撞内部元数据版本(出于内部原因*),从而导致错误 3961。
因此,您所看到的行为是预期的,只是没有很好地记录。
* TRUNCATE TABLE 的当前实现不生成行版本。碰撞元数据版本是确保正确行为的最简单方法。
| 归档时间: |
|
| 查看次数: |
3395 次 |
| 最近记录: |