读取行和表被锁定以进行更新

时间:2014-11-07 17:32:34

标签: sql-server tsql

锁 大家好,我正在研究锁并试图理解它们。

我的目标也是,能够在更新时锁定一行,但仍然允许用户能够从表中读取。  在我的阅读中,我读到了这个

"共享锁(S) 对于在悲观并发模型下读取的数据,保留共享锁。在保持共享锁的同时,其他事务可以读取但不能修改锁定的数据。 "

所以我在一次交易中有这个。

BEGIN TRAN

USE AdventureWorks2008R2

UPDATE Person.Address 
SET AddressLine2 = 'Test Address 2'
WHERE AddressId = 5

现在在下一个交易中,我有同样的事情

BEGIN TRAN

USE AdventureWorks2008R2



UPDATE Person.Address 
SET AddressLine2 = 'gar'
WHERE AddressId = 5

--ROLLback

我没有按照我的预期执行,但在另一项交易中

select * from AdventureWorks2008R2.Person.Address

这最后的转换并没有运行,我不确定为什么。既然它说我可以读取数据

我还看了它似乎工作的更新锁,因为我不能更新行,除非我comit或回滚转换。但是,我无法选择交易。我唯一可用的选项是使用独占锁并读取未提交的? 只是寻找锁定正在更新的行的最佳方法,但同时允许读取该行和表。 谢谢。

1 个答案:

答案 0 :(得分:1)

取决于资源锁定的取消模式。

这里有三种相关的锁定模式。共享(S),更新(U)和独占(X)。

锁兼容性矩阵如下

+---+----+----+---+
|   | S  | U  | X |
+---+----+----+---+
| S | ✓  | ✓ | ✘ |
| U | ✓  | ✘ | ✘ |
| X | ✘  | ✘ | ✘ |
+---+----+----+---+

即。共享与其他共享或更新兼容。更新锁与共享锁兼容,但不与其他更新锁兼容,并且独占锁与任何东西都不兼容。

第一个事务获取U锁,然后将其转换为X锁以实际执行更新。第二个事务被阻止,因为S锁与X锁不兼容。

允许在更新行时读取行的唯一方法是使用read uncommitted或其中一个快照隔离级别。后者将返回"之前"行的值。前者可以回归"脏"数据。即"之后"价值,但在承诺之前。