READ_COMMITTED_SNAPSHOT和SNAPSHOT隔离中的共享锁

时间:2012-11-13 10:03:17

标签: sql-server sql-server-2008 read-committed-snapshot snapshot-isolation

我在微软的网站上看过 http://msdn.microsoft.com/en-us/library/ms173763.aspx

除了正在恢复数据库时,Sql Server在读取数据时不会请求锁定。

这是否意味着使用READ_COMMITTED_SNAPSHOT / SNAPSHOT ISOLATION的Sql Server根本不使用共享锁? 怎么可能?

例如,如果有2个交易。 第一个事务T1想要更新某一行。 第二个事务T2开始读取同一行(此事务将其复制到某个输出缓冲区,响应缓冲区或在Sql Server中调用的任何内容)。 同时事务T1开始更新该行(它首先创建了版本化的行)。

事务T2是否有可能读取未提交的数据? 请记住,事务T2在T1更新之前开始复制该行,因此该行没有排他锁。

这种情况是否可行?如果在复制数据时不设置该行的共享锁,如何避免这种情况呢?

2 个答案:

答案 0 :(得分:2)

除了逻辑锁之外,还有物理latches来保护数据库结构(特别是在本例中,页面)。锁存器保护任何更改(位的修改),与隔离级别无关。因此,即使T1没有获取锁,它仍然需要在它读取的页面上获取共享锁存器,否则它将成为对它所读取的结构进行低级并发修改的牺牲品。只有在获得页面独占锁存器时,T2才能修改包含它修改的行的页面。因此T1只能在T2修改它之前看到行的图像(因此行是T1想要的那个),或者在T2完成后对行进行修改(现在T1必须查找前一行图像) version store)。

锁存协议必须遵循所有隔离级别,包括读取未提交和版本化读取(即快照和朋友)。

答案 1 :(得分:0)

  

这是否意味着使用READ_COMMITTED_SNAPSHOT / SNAPSHOT ISOLATION的Sql Server根本不使用共享锁?怎么可能?

这是可能的,因为SQL Server正在从SNAPSHOT读取,而SNAPSHOT根本不会通过任何更改。它在当前事务开始时在DB的状态下已经冻结,忽略了来自其他进程的未提交事务。这是由SQL Server保留 tempdb 中记录的快照row-versioned)副本,以便交易引用,让当前正在进行的数据/索引页面已更改。

  

事务T2是否有可能读取未提交的数据?请记住,事务T2在T1更新之前开始复制该行,因此该行没有排他锁。

以上叙述已经解释了这一点。但为了说明(简化):

情景1:

T1: begin tran (implicit/explicit)
T1: read value (4)
T2: read value (4) -- *
T1: update value to (8)

* - This is the committed value at the time the T2 transaction started

情景2:

T1: begin tran (implicit/explicit)
T1: read value (4)
T1: update value to (8)
     version of the row with the value (4) is made
T2: read value (4) -- * from the versioned row
T1: commit

* - (4) is [still] the *committed* value at the time the T2 transaction started