SQL Server 中的已提交读快照和快照隔离级别取消了大多数锁定,除了一个:写入者仍然锁定其他写入者。
文档蹑手蹑脚地说了这么多,随后没有记录任何其他非常有趣的内容:
它真的只是一个被独占锁定的修改行吗?或者它也可以是不相关的行(例如,在索引中相邻)或页面?
我确实查看了锁,sys.dm_tran_locks
并且我只在未提交的事务期间看到修改行上的排他锁 - 页面仅锁定为IX
.
我还测试了两个事务是否可以在一个非常小的表中的两个未提交事务期间同时修改两个不同的行,该表可能适合一页并且效果也很好。
如果确实只有修改的行被独占锁定,那么如果它确保没有两个连接同时写入同一行,那么这将为具有对数据库的独占访问权限的应用程序提供无锁写入的保证。
这在我想到的场景中是可能的——但是如果页面锁定起作用,几乎没有办法做这样的事情,因为无法预测哪些行会受到影响。
关于锁和锁升级的一般规则:
行级锁可以升级为表级(或分区级)锁。因此,在某些情况下,可能会锁定不相关的行。
这些情况记录在这里。另请注意,可以使用
LOCK_ESCALATION
table 选项禁用锁定升级。还有一些查询计划使用页锁,一些查询计划需要读取被另一个事务锁定的行以确定是否应该修改它。例如
update foo where someUnindexedColumn = 'someval'
,将需要读取每一行,因此将被任何其他写入器阻塞。请注意这一点(我们将在最后一段中需要它):
关于
SNAPSHOT
隔离级别的规则:简而言之,在这个隔离级别:
但是,文档没有提到“作者不阻止作者”,因此我们可以安全地假设作者确实可以在 SNAPSHOT 隔离级别中阻止作者。
有关快照如何工作的更多信息可以在事务锁定和行版本控制中找到:
和下
上面的这一段,尤其是在要修改数据之前确实获得了锁的部分解释了阻塞(作者对作者)行为(并考虑到顶部提到的“重要”注释):
所以在
SNAPSHOT
隔离下: