1.问题
最近笔者接到一个新的开发需求:将多张相同字段的MySQL数据表合并为一张,一听我就乐了,这不就是几行INSERT INTO SELECT FROM…的事儿嘛。在痛快的执行完准备交付的时候,发现了一个问题:
合并好的数据表中的id居然不是连续自增的,也就是说合并的几张数据表中每两张表的Id中间没有续上。
合并前的数据是长这样的
合并好之后的数据是长这样的
可以发现4下来就是8了,11下来是15
2.分析
通过仔细的研究之后发现,对于批量插入数据语句,MySQL提供了批量申请自增id的策略:
- 语句执行过程中,第一次申请自增id,会分配1个(2的0次方)
- 1个用完以后,这个语句第二次申请自增id,会分配2个(2的1次方)
- 2个用完以后,还是这个语句,第三次申请自增id,会分配4个(2的2次方)
也就是说当我执行下面这条语句时(user01一共四条数据)
INSERT INTO user (name, age) SELECT name, age from user01;
- 第一次申请自增id会分配1个,1 < 4
- 第二次申请自增id会分配2个,1+2 < 4
- 第三次申请自增id会分配4个,1+2+4 > 4,终止
此时1 + 2 + 4 = 7 > 4,申请自增id的操作就会停止。
因为已经申请了7个id了,所以当我们执行第二条SQL语句时,插入数据的id就会从8开始,此时AUTO_INCREMENT的值也会是8
3.解决方案
笔者采用的操作是在Navicat中修改自动递增的值来保证它的id连续:直接将自动递增的值删除,然后保存
当然,这个理论上是不能解决根本问题的,希望大家有建议也可以多多评论。
4.结论
这么设计的主要原因是为了提升性能,所以自增id只保证是递增的,但不保证是连续的!