1

我有一个 SQL Server 2008 数据库SET ALLOW_SNAPSHOT_ISOLATION ON和一个带有列 ID(主键)和 SSN(唯一非聚集索引)的 Person 表。

数据库中的其中一行是 ID = 1,SSN = 776-56-4453。

一对一连接,发生这种情况:

set transaction isolation level snapshot
begin transaction snapshot
while (1 = 1) select * from person where SSN = '777-77-7777'

然后在另一个连接上:

update person set SSN = '555-55-5555' where ID = 1

正如预期的那样,即使在第二个连接完成执行后,第一个连接仍将 SSN 显示为“777-77-7777”。第一个连接的执行计划在 SSN 上显示“聚集索引搜索”,但是如果另一个连接上的索引键已更新,第一个连接如何继续使用该索引?

SQL Server 是否会做任何特别的事情来保持索引的多个版本以适应这种情况?

我试图了解快照隔离级别的性能特征,因此想确认 SQL Server 足够聪明,即使在从行的先前版本中检索过时数据时也可以使用现有索引。

4

2 回答 2

1

据我所知(使用DBCC INDDBCC PAGE 描述here并查看sys.dm_tran_version_store)在启用快照隔离的数据库中更新索引键时,会发生以下情况。

  1. 原始行被复制到版本存储中。
  2. 原始行被标记为幽灵并更新版本指针以指向正确的位置。
  3. 为新键值插入一个新行。
  4. 稍后,幽灵清理过程运行并删除该行。

您的方案中唯一的区别似乎是幽灵清理过程不会清理该行,直到未完成的快照隔离事务不再需要它。即 BTree 包含旧键值和新键值的行,直到不再需要它们,这允许旧值上的索引查找仍然像以前一样工作。

于 2012-05-20T11:28:08.447 回答
0

通过快照隔离,SQL Server 会将正在修改的数据的“快照”放入 tempDB,其他连接将从那里读取。因此,您在这里的第一个连接是读取它的值以及从 tempDB 中的快照副本中涉及的所有相关索引

于 2012-05-20T09:21:13.417 回答