计算多行插入语句的插入 ID 的可靠性

Reliability of computing insert ids of a multi-row insert statement

我在一条语句中进行多次插入,例如:

INSERT INTO table (foo) VALUES ('aaa'), ('bbb'), ('ccc')

当我尝试获取最后一个插入 ID 时,MySQL (PDO) 只给出第一个插入 ID。

因为我知道我插入了多少项目(上面例子中的三个项目),只要INSERT作为交易完成,手动计算插入的id是否可靠?

例如,如果 MySQL returns 的第一个插入 ID 是 5,我可以安全地假设上述 INSERT 示例的插入 ID 是 567?或者如果另一个用户同时插入,即使它们是作为事务完成的,是否仍然存在重叠的可能性?


建议的重复 question 虽然相似,但没有清楚地回答我的问题。那里接受的答案只说只给出第一个插入 id 是预期的行为,我同意,但我的问题是关于手动计算方法的可靠性。那里的评论部分也看起来很有趣。

MySQL 的 JDBC 连接器的代码依赖于连续的 id 批次。

MySQL协议只returns生成第一个id。但是 JDBC 接口要求连接器实现一个 returns 生成所有 id 的方法。所以它必须假设第一个后面的 id 是连续值。

但每条规则都有例外。

  • 如果您执行“混合模式”的 INSERT,则假设无效。这意味着您执行多行插入,其中 一些 行指定一个值,但其他行期望生成一个新 ID。

  • 如果您执行“混合模式”或“批量”插入(后者类似于 INSERT...SELECT 或加载数据,或任何其他时间行数事先不知道),并且 innodb_autoinc_lock_mode=2(“交错”)并且在另一个会话中存在任何类型的并发 INSERT,那么您的 INSERT 的 id 集可能不连续。

要了解有关这些问题的更多详细信息,请仔细阅读 https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html

我不想做假设。

我插入多行然后立即需要它们的 ID 的主要地方是在“规范化”一堆值以便我可以改用 ID 时。

这样做时:

  1. 从包含要规范化的字符串的临时文件 table 开始,
  2. 使用 INSERT...SELECT DISTINCT ... 将它们放入 id:name 查找 table
  3. 使用UPDATE .. JOIN .. SET temp.id = norm.id WHERE temp.name = norm.name.

高效、多线程安全等更多详情:http://mysql.rjweb.org/doc.php/staging_table#normalization