【问题标题】:Reliability of computing insert ids of a multi-row insert statement计算多行插入语句的插入 ID 的可靠性
【发布时间】:2021-05-01 13:40:25
【问题描述】:

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

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

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

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

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


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

【问题讨论】:

    标签: php mysql database pdo innodb


    【解决方案1】:

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

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

    但每条规则都有例外。

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

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

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

    【讨论】:

    • 谢谢。所以我想只要我不手动跳转自动增量值,就可以安全地假设 id 是连续的,而不管其他用户的同时会话。
    【解决方案2】:

    我不想做任何假设。

    我插入多行然后立即需要它们的 id 的主要地方是“规范化”一堆值以便我可以使用 id 代替。

    当这样做时:

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

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

    【讨论】:

      猜你喜欢
      • 2010-12-11
      • 1970-01-01
      • 2018-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多