最近用MySQL,使用自增列,在执行批量插入时发现不连续现象。这里并没有删除操作,不是删数据造成的空洞。
后来发现空洞大小和批量大小有些关系,这取决于MySQL生成新的auto_increament_value的方法。
新的自增值会是一个2的n次方的数字。这个数字是大于批量插入数据的最大自增值的2的n次方中最小的那个。
不知道这个行为是不是我特定的MySQL版本造成的,我的版本是5.5.47。
请教大神,是不是有新版本或已经发布的补丁,或者什么设置能改变这个行为,谢了先。我试了如下一些批量大小发现这个规律,请看下表:
一批插入的数据量,为新数据准备的自增值
============= =================
1,2
2,4
3,4
4,8
5,8
6,8
7,8
8,16
9,16
10,16
11,16
12,16
13,16
14,16
15,16
16,32下面脚本给有兴趣的小伙伴参考。用来产生不连续自增值的脚本:
drop table if exists ttt;
drop table if exists tsource;create table if not exists ttt (id int auto_increment primary key, name varchar(50));
create table if not exists tsource (name varchar(50));
insert into tsource values
('aaa'),
('bbb'),
('ccc'),
('ddd');insert into ttt (name)
select name from tsource;insert into ttt (name) values ('eee');select * from ttt;

解决方案 »

  1.   

    或许可以插入前set AUTO_INCREMENT = max(id)+1  ,因为官方没有公布这个bug,  改变后不知道会不会影响存储,
      

  2.   

    insert select语句对于自增列会预分配  如果不够就翻倍       
    所以你插入4条语句就分配自增列到8  插入10条语句肯定就分配到16  插入20条语句就分配到32
      

  3.   

    这个测试结果进一步指向一个结论:MySQL团队就是这样设计的,保证连续并不在自增列设计的考虑中。
      

  4.   

    http://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html#innodb-auto-increment-initialization,后面提到了自增列,但还是想不通为什么这样设计,你的列子中在首次插入四条数据之后就已经 AUTO_INCREMENT=8了 ,想不通啊想不通
      

  5.   

    其实这只是演示自增列在做批量插入时候行为的示例代码。我什么也没设计,如果说MySQL为什么这么设计自增列的行为,我也只能猜测。可能MySQL的这种批量插入自增列的行为是出于性能考虑,不用在批量的每条插入操作中都请求自增量的增加操作。毕竟为保证并发安全这是需要同步处理开销的。如果预先留出一部分,那么在此之内的批量插入就可以简单地在线程局部+1了,因为其他线程会用留出一定空间的新的全局计数值。
      

  6.   

    其实不然,MYISAM就好好的
      

  7.   

    这里涉及到步长的问题,本次获取的id,是目前的id数加步长。
    从来没有往这个表里写数据,那么步长就是1,否则步长就是上次插入数据的条数。
    比如,现在的最大id是N1,往表里写入了N2条数据,那么下次写入数据,就是从N1+N2开始。
      

  8.   

    https://blog.csdn.net/weixin_39004901/article/details/84871909自增键空洞是MySQL的特性导致的,具体跟binlog和innodb_autoinc_lock_mode有关,上述地址有说明。