下面的两个会话尝试更新同一行的场景由 Paul White 提供。
场景一:
- 会话 1
U
在读取时获取基表行的锁。- 会话 2 阻塞,等待获取
U
基表中的同一行。- 会话 1 将值设置为 10 并提交。
- 会话 2 获取了它的
U
锁并且发现没有什么可做的,因为现在 Value != 0。结果:值设置为 10。
根据 Paul 的说法,会话 2 已经找到了需要更新的行,但它被阻止了。当阻塞消失并且会话 2 获得 U 锁时,它需要再次检查条件吗?我理解正确吗?对我来说这有点奇怪。会话找到了这一行,这是因为它评估了导致识别该行的过滤器。为什么在实际更新之前需要再次检查条件?
答案已隐含在您发布的文本中。
最初满足条件
Value = 0
,但当它获得锁定时,条件不再满足。U
Value = 0
SQL Server 仅在获取锁后从行中读取值。
SQL语句
应该更新
ID = 1 AND Value = 0
更新时的行。以前的版本中没有。这就是这些测试乐观并发违规的方法有效的原因。