简体   繁体   English

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

[英]Reliability of computing insert ids of a multi-row insert statement

I am doing multiple inserts in one statement eg:我在一条语句中进行多次插入,例如:

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

When I try to get the last insert id, MySQL (PDO) only gives the first insert id.当我尝试获取最后一个插入 ID 时,MySQL (PDO) 仅提供第一个插入 ID。

Since I know how many items I inserted (three items from the example above), is it reliable to manually compute the inserted ids as long as the INSERT is done as a transaction?因为我知道我插入了多少项目(上面示例中的三个项目),只要INSERT作为事务完成,手动计算插入的 ids 是否可靠?

Eg, if the first insert id that MySQL returns is 5 , can I safely assume that the insert ids of the above INSERT example is 5 , 6 , 7 ?例如,如果 MySQL 返回的第一个插入 ID 是5 ,我可以安全地假设上述INSERT示例的插入 ID 是567吗? Or is there still a possibility of overlap if another user inserts at the same time, even if they were done as a transaction?或者,如果另一个用户同时插入,是否仍然存在重叠的可能性,即使它们是作为事务完成的?


The suggested duplicate question , while similar, does not clearly answer my question.建议的重复问题虽然相似,但没有明确回答我的问题。 The accepted answer there only says it is expected behavior that only the first insert id is given, which I agree, but my question here is about how reliable is the method of the manual computation.那里接受的答案只说只给出第一个插入 id 是预期的行为,我同意,但我的问题是关于手动计算方法的可靠性。 The comments section there also looks anecdotal.那里的评论部分也看起来很有趣。

The code for MySQL's JDBC connector relies on the batch of id's being consecutive. MySQL 的 JDBC 连接器的代码依赖于 id 的批次是连续的。

The MySQL protocol only returns the first id generated. MySQL 协议只返回生成的第一个 id。 But the JDBC interface requires the connector to implement a method that returns all the id's generated.但是 JDBC 接口要求连接器实现一个返回所有生成的 id 的方法。 So it must make an assumption that the id's following the first are consecutive values.所以它必须假设第一个后面的 id 是连续值。

But there's are exceptions to every rule.但每条规则都有例外。

  • If you execute an INSERT that is "mixed-mode" then the assumption is not valid.如果您执行“混合模式”的 INSERT,则该假设无效。 This means you do a multi-row INSERT where some rows specify a value but other rows expect a new id to be generated.这意味着您执行多行 INSERT,其中一些行指定一个值,但其他行期望生成一个新的 id。

  • If you execute an INSERT that is "mixed-mode" or "bulk" (the latter is like INSERT...SELECT or LOAD DATA, or any other time where the number of rows is not known in advance), and innodb_autoinc_lock_mode=2 ("interleaved") and there are concurrent INSERTs of any kind in another session, then the set of id's for your INSERT might not be consecutive.如果执行“混合模式”或“批量”插入(后者类似于 INSERT...SELECT 或 LOAD DATA,或行数事先未知的任何其他时间),并且innodb_autoinc_lock_mode=2 (“交错”)并且在另一个 session 中存在任何类型的并发 INSERT,那么您的 INSERT 的 id 集可能不是连续的。

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

I prefer not to make assumptions.我宁愿不做假设。

The main place where I have inserted multiple rows, then immediately needed their ids, was when "normalizing" a bunch of values so I can use ids instead.我插入多行然后立即需要它们的 id 的主要地方是在“规范化”一堆值以便我可以改用 id 时。

When doing that:这样做时:

  1. Start with a temp table that contains the strings being normalized,从包含要规范化的字符串的临时表开始,
  2. Use INSERT...SELECT DISTINCT... to put them into the id:name lookup table使用INSERT...SELECT DISTINCT...将它们放入 id:name 查找表
  3. Use UPDATE.. JOIN.. SET temp.id = norm.id WHERE temp.name = norm.name .使用UPDATE.. JOIN.. SET temp.id = norm.id WHERE temp.name = norm.name

It's efficient, multi-thread-safe, etc. More details: http://mysql.rjweb.org/doc.php/staging_table#normalization它高效,多线程安全等更多细节: http://mysql.rjweb.org/doc.php/staging_table#normalization

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM