【问题标题】:MySQL Insertion: Race conditionMySQL 插入:竞争条件
【发布时间】:2016-08-17 13:39:04
【问题描述】:

我想知道是否存在在插入查询中实际发生竞争条件问题的真实案例。所以我有一个包含以下字段的“用户”表:

User:
iduser | idcompany | name | email

我为此表使用复合主键 (iduser, idcompany)。这些字段均未设置为 AUTO_INCREMENT。我通过会话变量获取字段“idcompany”的值,因此这不是真正的问题。但是,我使用 getNextUserId() 函数通过这样的选择查询获取下一个有效的 iduser 值:

SELECT MAX(iduser) + 1 AS next_iduser FROM User WHERE idcompany = {myCompanyId};

我想知道是否存在由于竞争条件而在数据库中插入 (iduser, idcompany) 的重复组合的任何情况,如果是,这种情况如何可能。 MySQL在插入时不会锁定表吗? (iduser, idcompany) simple 的重复组合不会被拒绝,或者我的表中真的可以有一个重复的主键吗?我知道完全防止竞争条件的策略,例如使用 AUTO_INCREMENT 主键、使用 SQL 事务或手动锁定“用户”表,但我想了解在这种情况下可能的竞争条件背后的机制以及真正的问题是什么这个实现。现在,出于显而易见的原因,这些字段在我的表中都不需要是唯一的,但我想知道例如对 iduser 的 UNIQUE 约束是否会改变我面临的场景以及为什么会发生这种情况。

【问题讨论】:

  • 它在插入期间锁定,但在同一公司的 10 个用户都尝试注册并且您必须运行 SELECT 以找到下一个 ID 以使用 10 次时没有锁定。您确实应该在事务中执行此操作,但假设您使用的是 PDO 或 MYSQLI 并且数据库表是 INNODB
  • 你不妨看看SELECT..... WITH LOCKhere in the manual
  • 这与@RiggsFolly 的评论有关。使用intention lock。没有人会明智地使用 max。
  • @RiggsFolly 我对这个问题的解释是 OP 想要理解某个设计的含义。该问题清楚地表明,OP 知道其他解决方案来避免这种竞争条件。
  • @RiggsFolly 在最后一段中有多个问题。或许你可以制定一个答案。

标签: mysql database insert race-condition composite-primary-key


【解决方案1】:

您写道,您在 iduser、idcompany 字段上有一个复合主键。此约束将防止表具有重复的 iduser、idcompany 对。没有锁定可能发生的最坏情况是违反主键会阻止用户的创建。

【讨论】:

  • 所以即使出现竞争条件,我也永远不会有重复的对?我当前的实现是否可以接受?
  • 复合主键(或唯一索引)约束可以完美处理这种特定的竞争条件。
  • 本书中只有 2 个有意义的 cmets,因为我看到它是关于竞争条件的。一是关于max()的使用。另一个是关于在回滚中重用 AI 的常见问题解答。所以我认为Shadow的答案在这里很好。
  • Shadow,我冒昧地编辑了您的答案。相应修改。
  • @iiirxs 您的实现是可以接受的,因为由于主键约束,您不会担心那里有重复项。另一方面,如果存在通过您的 max() 查询为 2 个或更多客户端分配相同 ID 的情况(这完全有可能),则只有其中一个会得到预期结果,其他会看到错误,更多具体来说,您的应用程序将在 INSERT 操作期间收到错误 - 如何处理此类错误取决于您
猜你喜欢
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 2012-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多