MySQL的自增长列(auto-increment)实现机制

MySQL auto-increment

Posted by alovn on October 22, 2021

自增长是MySQL中常用的一个属性。在InnoDB存储引擎的内存中,对每隔含有自增长列的表都有一个自增长计数器。对有自增长的表进行插入时,会对这个计数器进行初始化,执行下面的语句得到计数器的值:

1
select max(auto_increment_col) from t for update;

插入操作会根据这个自增长的计数器加1赋值给自增长列。这种自增长方式称为AUTO-INC Locking。这是一种特殊的表锁机制,为了提高插入性能,锁不是在事务完成后才释放,而是在执行完自增长值插入的SQL语句后立即释放。

不过这种锁存在一定并发性能问题,必须等待前一个插入的SQL完成。从MySQL5.1.22版本开始InnoDB提供了一种轻量级的互斥量自增长实现机制,它极大提高了自增长值的插入性能。MySQL同时从这个版本开始提供了一个参数 innodb_autoinc_lock_mode 控制自增长的模式,默认值为1。

innodb_autoinc_lock_mode说明
0采用之前表锁AUTO-INC Locking机制(不推荐)
1默认值。对于能确定数量的插入语句采用互斥量的方式累加。对不能确定数量的插入语句还是采用之前的AUTO-INC Locking表锁。
2对所有的插入语句使用互斥量的方式。但是并发插入时自增值可能会不连续,对于使用statement replication可能会出现问题,应该使用row replication。

在事务下在执行插入语句,并回滚后,再次执行并成功插入后会发现之前回滚的自增长值就会跳过去,不再使用。为什么这样应该很好理解了。

此外,InnoDB存储引擎中的自增长列还必须是索引,若是联合索引它还必须是索引键的第一个列,否则会抛出异常。在MyISAM存储引擎下并没有这个问题,并且MyISAM和InnoDB的自增长实现方式也不同,因为MyISAM是表锁机制,自增长时不用考虑并发插入的问题,所以它的插入性能也是很差的。