事务是不是会停止 MySQL 中的所有竞争条件问题?

Posted

技术标签:

【中文标题】事务是不是会停止 MySQL 中的所有竞争条件问题?【英文标题】:Does a transaction stop all race condition problems in MySQL?事务是否会停止 MySQL 中的所有竞争条件问题? 【发布时间】:2010-05-11 07:29:35 【问题描述】:

考虑这种情况:

    开始交易 使用 auto_increment 键将 20 条记录插入表中 获取第一个插入ID(假设它是153) 更新该表中id >= 153 所在的所有记录 提交

第 4 步安全吗?

也就是说,如果另一个请求几乎同时到来,并且在上面的第 2 步之后,但在第 4 步之前,又插入了 20 条记录,会不会出现竞态条件?

【问题讨论】:

为什么你会有一个单独的更新步骤,而不是一开始就插入正确的数据?那是相当奇怪的。如果您首先插入正确的数据,则无需担心“竞争条件”。更新WHERE id > 153 也是一个很奇怪的查询。自动增量 id 对它们没有逻辑,因此您永远不应该(据我所知)仅基于 id 进行更新。最后,我不知道任何“第一个插入 id”功能。 @ButtleButkus dev.mysql.com/doc/refman/5.0/en/… "如果您使用单个 INSERT 语句插入多行,LAST_INSERT_ID() 将返回为第一个插入行生成的值" 你对 LAST_INSERT_ID() 的看法是对的,但这并没有改变这样一个事实,即问题似乎是关于假设情况,如果遵循基本的数据库结构和过程,这种情况永远不会存在。为什么您的更新标准永远是无意义的 id 的值?我想不出任何理由。我不会称其为“竞争条件”,因为它是荒谬的。当您可以插入正确的值开始时,为什么要在插入后立即更新?这些才是这个问题没有意义的真正原因。 我真的不记得最初的问题(大约 3 年前),但我认为这是必要的。 :) 不管推理如何,我相信这个问题的基本原则是合法的——在该事务中,在插入插入期间插入的记录是否可以“看到”并受到更新的影响? 【参考方案1】:

也就是说,如果另一个请求几乎同时到来,并且在上面的第 2 步之后,但在第 4 步之前,又插入了 20 条记录,会不会出现竞态条件?

是的,会的。

2140 的记录将被2 事务锁定。

事务1 将被阻塞并等待事务2 提交或回滚。

如果事务2 提交,那么事务1 将更新40 记录(包括由事务2 插入的记录)

【讨论】:

你能澄清一下吗?你是说有问题还是没有?【参考方案2】:

我认为这不能归类为竞争条件,而是归类为 DMBS 特定行为。基本上,如果 DBMS 锁定了新插入的记录,那么在提交第二个事务之前,第一个事务将不会看到来自第二个事务的记录。

当然还有锁定表的问题,如果第一个事务对表进行写锁定,那么第二个事务将在写入时被阻塞,直到第一个事务完成。不确定标准 mysql 是否提供这种功能。我知道 MSSQL 服务器确实如此。

【讨论】:

以上是关于事务是不是会停止 MySQL 中的所有竞争条件问题?的主要内容,如果未能解决你的问题,请参考以下文章

处理事务数据库表中的竞争条件

使用数据库事务防止竞争条件 (Laravel)

停止刷新令牌的竞争条件?

Java MySQL 防止竞争条件

NHibernate 事务和竞争条件

阿里一面 | 说说你对 MySQL 死锁的理解