两阶段锁定实际上可以防止丢失的更新吗



两相锁定被认为是确保串行执行的解决方案。然而,我不确定它如何充分解决读-修改-写周期中丢失的更新问题。我可能忽略了/误解了这里的锁定机制!

例如,假设我们有一个使用2PL:运行的数据库

给定一个包含整数列email_count的SQL表account,假设我们的数据库中有以下记录:

| ID | email_count |
| ----- | ----- |
| 1    | 0  |

现在假设我们有两个同时执行的事务,T1T2。两个事务都将从ID=1的accounts读取email_count,将计数值增加1,然后写回结果。

这里有一个场景,其中2PL似乎解决了丢失的更新问题(T1表示事务1(:

T1->获得一个非独占的共享读锁。从ID=1的email_count读取。获取结果0。应用程序为以后的写入设置一个新值(0+1=1(。

T2->还获得一个非独占的共享读锁。读取ID=1的"email_count"。获取结果0。应用程序还设置了一个新值(使用一个现已过时的先决条件(,即1(0+1=1(。

T1->获得一个独占写锁,并将新值(1(写入我们的记录。这将阻止T2写入。

T2->试图获得写锁,以便它可以写入值1,但被迫等待T1完成其事务并释放T1自己的所有锁。

现在我的问题是:

一旦T1完成并释放其锁(在2PL的"收缩"阶段(,T2仍然具有过时的email_count值1所以当T1完成并且T2继续其写入(email_count=1(时;失去";来自T1的原始更新。

如果T2具有读锁,则在T2释放读锁之前,T1无法获取独占锁。因此,您所描述的执行序列不可能发生。T1将被拒绝写入锁定,并且T2继续事务。

T1->获取独占写锁并将新值(1(写入我们的记录。这将阻止T2写入。

上述步骤无法执行,因为T2已经具有共享读取锁定,所以T1应该等到T2释放共享读取锁定。

但是,T2无法释放共享读取锁定。

因为,根据2PL,如果T2想要释放共享读锁,T2应该首先获得写锁。

但是T2无法获得写锁定,因为T1已经具有共享读锁定。

所以,是的,这是僵局。这就是2PL防止丢失更新的原因。即使它可能会产生死锁。。

最新更新