我有一个带有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是否足够智能,即使在从行的先前版本中检索过时数据时也可以使用现有索引。
答案 0 :(得分:0)
通过快照隔离,SQL Server会将正在修改的数据的“快照”放入tempDB,其他连接将从那里读取。因此,您的第一个连接是读取其值以及tempDB中快照副本所涉及的所有相关索引
答案 1 :(得分:0)
据我所知(使用DBCC IND
和DBCC PAGE
as described here并查看sys.dm_tran_version_store
)更新数据库中的索引键并启用了快照隔离时,发生的情况。
您的方案中唯一的区别似乎是ghost清理进程不清理该行,直到未完成的快照隔离事务不再需要它。即,BTree包含旧键值和新键值的行,直到不再需要它们为止,这使得对旧值的索引搜索仍然可以像以前一样工作。