两相锁定是索要用于确保串行执行的解决方案。但是,我不确定它如何在读-修改-写周期中充分解决丢失的更新问题。我可能忽略了/误解了这里的锁定机制!
例如,假设有一个使用2PL运行的数据库:
给定具有整数列account的SQL表email_count,让我们假设数据库中有以下记录:
| ID | email_count |
| ----- | ----- |
| 1 | 0 |现在假设我们有两个并发执行的事务,T1和T2。这两个事务都将从ID =1的email_count中读取accounts,将计数值增加1,并写入结果。
这里有一个场景,其中2PL似乎没有解决丢失的更新问题(T1代表事务1):
T1 ->提供了一个非排他的、共享的读锁。从email_count读取ID = 1,获取结果0。应用程序为以后的写入设置一个新值(0 +1= 1)。
T2 ->还获得一个非排他的、共享的读锁。从`email_count‘读取ID = 1,获取结果0。应用程序还设置了一个新值(使用一个现在陈旧的预条件),即1 (0 +1= 1)。
T1 ->获得一个独占的写锁,并将新值(1)写入我们的记录。这将阻止T2编写。
T2 ->试图获得写锁,以便能够写入值1,但被迫等待T1完成其事务并释放t1所有自己的锁。
现在我的问题是:
一旦T1完成并释放其锁(在我们的2PL的“收缩”阶段), T2 仍然的值为1!,所以当T1完成并且T2继续其写( email_count = 1)时,我们将“丢失”T1的原始更新。
发布于 2022-03-20 18:54:15
如果T2有读锁,则在T1释放读锁之前,T1无法获取独占锁.因此,您描述的执行顺序不可能发生。T1将被拒绝写入锁,而T2将继续该事务。
发布于 2022-08-05 09:43:31
T1 ->获得了一个独占的写锁,并将新值(1)写入我们的记录。这将阻止T2编写。
上面的步骤不可能发生,因为T2已经有了共享读锁,所以T1应该等到T2释放共享读锁。
但是,T2不能释放共享读锁。
因为,根据2PL,如果T2想要释放共享读锁,T2应该首先获得写锁。
但是T2无法获得写锁,因为T1已经共享了读锁。
所以,是的,这是僵局。这就是为什么2PL防止丢失更新。即使它可能产生僵局..。
https://stackoverflow.com/questions/71548866
复制相似问题