首页 > 解决方案 > 我是否保证在 mysql 中使用单个插入语句获得连续的 id?

问题描述

我用一个 INSERT 查询插入 1000 行。查询返回第一个插入行的 id。firstId + i考虑到可能有多个插入查询同时运行,是否可以假设所有其他行都具有 id ?

标签: mysqlsql

解决方案


也许。通常是的,但在许多情况下这是不可靠的。

MySQL JDBC 驱动程序假设当您执行批量插入时,一批生成的自动增量值是连续的。

请参阅java.com.mysql.cj.jdbc.StatementImpl.getGeneratedKeysInternal()中的代码

简化逻辑,相关位为:

long beginAt = getLastInsertID();
for (int i = 0; i < numKeys; i++) {
    row[0] = StringUtils.getBytes(Long.toString(beginAt));
    beginAt += this.connection.getAutoIncrementIncrement();
}

所以它从插入的第一个行的 id 开始,并假设后续生成的 id 值只是下一个numKeys值,按配置设置递增auto_increment_increment(默认为 1)。

这会出错吗?是的,在少数情况下。例如:

  • 如果执行 multi-row INSERT,在同一语句中为某些行指定 NULL 并为其他行指定实整数值INSERT,则 JDBC 驱动程序假设所有值在返回值之后都是连续值LAST_INSERT_ID()是不正确的。

  • 如果您执行多行INSERT...ON DUPLICATE KEY UPDATEREPLACE某些行存在而其他行不存在,它将错误地报告一组连续生成的键。

  • 如果设置innodb_autoinc_lock_mode = 2(“interleaved”锁定模式),那么并发运行的多行 INSERT 语句可能不连续。他们每个人都会尽可能地生成 id 值,这将是不可预测的交错,就像洗牌的两半一样。见https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html


推荐阅读