手动增加主键 - 交易和竞赛条件

时间:2013-07-03 22:01:13

标签: mysql sql transactions race-condition

这可能不是一个现实世界的问题,但更像是一个学习主题。

使用PHP,MySQL和PDO,我知道auto_increment和lastInsertId()。考虑主键没有auto_incerment属性,我们必须使用类似SELECT MAX(id) FROM table的内容来检索最后一个id,手动递增,然后INSERT INTO table (id) VALUES (:lastIdPlusOne)。将整个代码换成beginTransactioncommit

这种方法安全吗?如果用户A和B同时加载此脚本,最终会发生什么?两笔交易都会失败?或者两者都会成功(例如,如果最后一个id为10,A将插入11而B将插入12)?

请注意,因为我是PHP& MySQL开发人员,因此我对这种情况下的MySQL行为更感兴趣。

2 个答案:

答案 0 :(得分:0)

如果两者都获得相同的最大值,那么首先插入的那个将成功,而其他(s)将失败。

要在不使用auto_increment字段的情况下解决此问题,您可以在执行作业的插入之前使用触发器(new.id = max),即相同的逻辑,但是在触发器中,因此DB服务器是控制它的人。

在服务器发生故障的情况下,不确定在主 - 主复制环境中这是否100%安全。

答案 1 :(得分:0)

这是@ eggyal评论,我在这里引用:

  

您必须确保在第一个(选择)查询中使用locking read来获取MAX();然后它将阻塞,直到提交事务。但是,这是非常差的设计,不应在生产系统中使用。