前言

InnoDB引擎默认需要为每个行记录的自增字段分配值,并且尽量是连续的值。

InnoDB是如何做到的?并在并发环境下有不错的效率。

使用了自增锁机制。在谈自增锁之前,需要先了解”插入数据的类型“。

插入数据的类型

需要给插入数据各种情景分类,做针对性优化。

simple insert

insert的时候通过SQI语句能知道将要插入的行数。

bulk insert

insert的时候通过SQI语句无法明确将要插入的行数。

mixed insert

在插入中的自增字段值,有些是自增长的,有些是确定的。例如:

1
insert into users(id, name) values (188, 'jack'),(321, 'tom'),(NULL, 'andy');

自增锁的模式

自增锁的运行模式通过参数innodb_autoinc_lock_mode来配置,它的默认值为1,它有3种模式。

0

这是自增锁最早实现的传统模式,叫AUTO-INC锁,是一种特殊的表级别锁

InnoDB存储引擎对每个含有⾃增长值的表都有⼀个⾃增长计数器, 当对含有⾃增长的计数器的表进⾏插⼊操作时, 执⾏如下的语句来得到计数器的值,加一后赋予当前行。

1
SELECT MAX(auto_inc_col) FROM t FOR UPDATE;

这也是一个加锁动作,但这个锁在拿到数据之后就会立即释放而不必等到会话提交,这是为了提升事务并发能力。

但在一些情况下依然会阻塞其他事务的insert操作。

1
INSERT INTO users (name, age) SELECT name, age FROM members WHERE age < 50;

上面这语句会有大量的行需要被插入,自增锁就会锁表很长一段时间。

1

这是InnoDB自增锁的默认模式

在此模式中,InnoDB增加提供了⼀种轻量级互斥量mutex的⾃增长实现机制, 这种机制不用锁表,⼤⼤提⾼了⾃增长值插⼊的性能。

这种模式对不同的插入数据类型做了不同的处理。

插入数据类型 处理方法
simple insert 使用互斥量mutex去对内存中的计数器进行累加操作
bulk insert 使用传统的AUTO-INC锁
mixed insert 没明白😂

2

此模式下,所有类型的插入数据的自增值都是通过互斥量产生,没有使用传统的AUTO-INC锁,所有它具有最好的并发能力。

但是因为并发插入的存在,它的自增值可能不是连续的。

修改自增长模式

编辑/etc/my.cnf进行静态设置,加入或修改如下行:

innodb_autoinc_lock_mode=2

然后重启MySQL。