1

我在微软的网站上读过 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 进行更新之前开始复制该行,因此该行上没有排他锁。

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

4

2 回答 2

3

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

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

于 2012-11-13T10:30:08.833 回答
0

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

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

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

上面的叙述已经说明了这一点。但是为了说明(简化):

场景一:

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

场景二:

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
于 2012-11-13T10:18:11.150 回答