READ_COMMITDE_SNAPSHOT和SNAPSHOT隔离中的共享锁



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

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

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

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

事务T2是否有可能读取未绑定的数据?请记住,事务T2在T1进行更新之前就开始复制该行,因此该行没有独占锁定。

这种情况可能发生吗?在复制数据时,如果不对该行设置共享锁,如何避免这种情况?

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

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

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

这是可能的,因为SQL Server正在从SNAPSHOT读取,而SNAPSHOT根本不会进行任何更改。在当前事务开始时,它已经在数据库的状态下被冻结,忽略了来自其他进程的未提交事务。这是通过SQL Server在tempdb中保留记录的快照(行版本)副本以供事务参考来完成的,从而更改当前正在进行的数据/索引页。

事务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

相关内容

  • 没有找到相关文章

最新更新