两阶段锁定真的可以防止更新丢失吗?

Does two phase locking actually prevent lost updates?

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

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

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

| ID | email_count |

| ----- | ----- |

| 1    | 0  |

现在假设我们有两个并发执行的事务,T1T2。两个事务都会从 ID = 1 的 accounts 读取 email_count,将计数值增加 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 仍然 有一个陈旧的 email_count 值1! 所以当 T1 完成并且 T2 继续写入时(email_count = 1),我们将“丢失”来自 T1 的原始更新。

如果T2有read-lock,T1在T2释放读锁之前无法获得排它锁。因此,您描述的执行顺序不会发生。 T1 将被拒绝写锁,T2 继续事务。