计算多行插入语句的插入 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 是 5
、6
、7
?或者如果另一个用户同时插入,即使它们是作为事务完成的,是否仍然存在重叠的可能性?
建议的重复 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 时。
这样做时:
- 从包含要规范化的字符串的临时文件 table 开始,
- 使用
INSERT...SELECT DISTINCT ...
将它们放入 id:name 查找 table
- 使用
UPDATE .. JOIN .. SET temp.id = norm.id WHERE temp.name = norm.name
.
高效、多线程安全等更多详情:http://mysql.rjweb.org/doc.php/staging_table#normalization
我在一条语句中进行多次插入,例如:
INSERT INTO table (foo) VALUES ('aaa'), ('bbb'), ('ccc')
当我尝试获取最后一个插入 ID 时,MySQL (PDO) 只给出第一个插入 ID。
因为我知道我插入了多少项目(上面例子中的三个项目),只要INSERT
作为交易完成,手动计算插入的id是否可靠?
例如,如果 MySQL returns 的第一个插入 ID 是 5
,我可以安全地假设上述 INSERT
示例的插入 ID 是 5
、6
、7
?或者如果另一个用户同时插入,即使它们是作为事务完成的,是否仍然存在重叠的可能性?
建议的重复 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 时。
这样做时:
- 从包含要规范化的字符串的临时文件 table 开始,
- 使用
INSERT...SELECT DISTINCT ...
将它们放入 id:name 查找 table - 使用
UPDATE .. JOIN .. SET temp.id = norm.id WHERE temp.name = norm.name
.
高效、多线程安全等更多详情:http://mysql.rjweb.org/doc.php/staging_table#normalization