1.问题

最近笔者接到一个新的开发需求:将多张相同字段的MySQL数据表合并为一张,一听我就乐了,这不就是几行INSERT INTO SELECT FROM…的事儿嘛。在痛快的执行完准备交付的时候,发现了一个问题:

mysql insert 后的自增字段值如何获取_数据合并好的数据表中的id居然不是连续自增的,也就是说合并的几张数据表中每两张表的Id中间没有续上。

合并前的数据是长这样的

mysql insert 后的自增字段值如何获取_mysql_02


合并好之后的数据是长这样的

mysql insert 后的自增字段值如何获取_数据库_03


可以发现4下来就是8了,11下来是15

2.分析

通过仔细的研究之后发现,对于批量插入数据语句,MySQL提供了批量申请自增id的策略:

  1. 语句执行过程中,第一次申请自增id,会分配1个(2的0次方)
  2. 1个用完以后,这个语句第二次申请自增id,会分配2个(2的1次方)
  3. 2个用完以后,还是这个语句,第三次申请自增id,会分配4个(2的2次方)

也就是说当我执行下面这条语句时(user01一共四条数据)

INSERT INTO user (name, age) SELECT name, age from user01;
  1. 第一次申请自增id会分配1个,1 < 4
  2. 第二次申请自增id会分配2个,1+2 < 4
  3. 第三次申请自增id会分配4个,1+2+4 > 4,终止

此时1 + 2 + 4 = 7 > 4,申请自增id的操作就会停止。
因为已经申请了7个id了,所以当我们执行第二条SQL语句时,插入数据的id就会从8开始,此时AUTO_INCREMENT的值也会是8

3.解决方案

笔者采用的操作是在Navicat中修改自动递增的值来保证它的id连续:直接将自动递增的值删除,然后保存

mysql insert 后的自增字段值如何获取_mysql_04


当然,这个理论上是不能解决根本问题的,希望大家有建议也可以多多评论。

4.结论

这么设计的主要原因是为了提升性能,所以自增id只保证是递增的,但不保证是连续的!