MySQL InnoDB:`FOR UPDATE` 和 `LOCK IN SHARE MODE` 的区别

MySQL InnoDB: Difference Between `FOR UPDATE` and `LOCK IN SHARE MODE`

两个锁定读取子句之间的确切区别是什么:

SELECT ... FOR UPDATE

SELECT ... LOCK IN SHARE MODE 

为什么你需要使用一个而不是另一个?

我一直在努力理解两者的区别。我会记录下我的发现,希望它对下一个人有用。

LOCK IN SHARE MODEFOR UPDATE 都确保没有其他事务可以更新选定的行。两者之间的区别在于它们在读取数据时如何处理锁。

LOCK IN SHARE MODE 不会阻止另一个事务读取被锁定的同一行。

FOR UPDATE 防止同一行的其他锁定读取(非锁定读取仍然可以读取该行;LOCK IN SHARE MODEFOR UPDATE 是锁定读取)。

这在更新计数器等情况下很重要,在这种情况下,您在 1 个语句中读取值并在另一个语句中更新值。这里使用 LOCK IN SHARE MODE 将允许 2 个事务读取相同的初始值。因此,如果两个事务都将计数器递增 1,则结束计数可能仅递增 1 - 因为两个事务最初读取的是相同的值。

使用 FOR UPDATE 会锁定第二个事务,使其无法读取值,直到第一个事务完成。这将确保计数器递增 2。

对于更新 --- 您通知 Mysql 选定的行可以在接下来的步骤中更新(在此事务结束之前),所以 mysql 不会此时将同一行集上的任何读锁授予任何其他事务。另一笔交易(是否为 read/write )应该等到第一笔交易完成。

For Share- 向 Mysql 表明您从 table 中选择行仅用于阅读目的,而不是在交易结束前修改。任意数量的事务都可以访问行上的读锁。

注意:如果这条语句(For update,For share)使用不当,可能会出现死锁。

无论哪种方式都能保证数据的完整性,只是数据库如何保证的问题。它是通过在事务相互冲突(即 FOR SHARE)时引发 运行time 错误来做到这一点,还是通过序列化任何会相互冲突的事务(即 FOR UPDATE)来做到这一点?

FOR SHARE (a.k.a.LOCK IN SHARE MODE):事务由于死锁而面临更高的失败概率,因为它们延迟阻塞直到收到更新语句的那一刻(此时它们要么阻塞直到所有读锁被释放,或者如果另一个写正在进行中则由于死锁而失败)。但是,只有一个客户端会阻塞并最终成功:如果其他客户端尝试更新,它们将因死锁而失败,因此只有其中一个会成功,其余客户端将不得不重试它们的事务。

更新:事务不会因死锁而失败,因为不允许它们同时 运行。例如,这可能是可取的,因为如果所有更新都在所有客户端之间序列化,那么它可以更容易地推理多线程。但是,它限制了您可以实现的并发性,因为在第一个事务完成之前,所有其他事务都会阻塞。

专业提示:作为一项练习,我建议您花一些时间在命令行上使用本地测试数据库和几个 mysql 客户端来亲自证明这种行为。这就是我自己最终理解差异的方式,因为在您实际看到它之前,它可能非常抽象。