在SQL Server中启用快照隔离时,如何更新聚簇索引?

时间:2012-05-20 05:14:28

标签: sql-server-2008 indexing snapshot-isolation

我有一个带有SET ALLOW_SNAPSHOT_ISOLATION ON的SQL Server 2008数据库和一个带有列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是否足够智能,即使在从行的先前版本中检索过时数据时也可以使用现有索引。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

  1. 将原始行复制到版本存储区。
  2. 原始行被标记为重影并更新版本指针以指向正确的位置。
  3. 为新键值插入新行。
  4. 稍后,ghost清理过程会运行并删除该行。
  5. 您的方案中唯一的区别似乎是ghost清理进程不清理该行,直到未完成的快照隔离事务不再需要它。即,BTree包含旧键值和新键值的行,直到不再需要它们为止,这使得对旧值的索引搜索仍然可以像以前一样工作。