MySQL性能(4)—AUTO_INCRMENT锁机制(innodb_autoinc_lock_mode参数配置)

在mysql的InooDB存储引擎中,常用的是自增(AUTO_INCRMENT)主键,因为InnoDB是聚簇索引。

使用自增主键可以保证数据行是按顺序写入的。若是使用无序的聚簇索引,例如UUID,不仅索引占用的空间更大,而且也会导致页分裂和碎片化现象。

引用自—高性能mysql第三版.png

使用自增索引,在高并发的情况下可能存在性能问题,一个就是间隙锁影响性能,而另一个就是AUTO_INCREMENT锁机制会影响性能。

1. InnoDB中AUTO_INCREMENT处理

若是在InnoDB中使用AUTO_INCREMENT机制,那么自增列必须是索引的一部分,以便可以等效于对表进行索引查找以获取最大列值。

innodb_autoinc_lock_mode配置可以控制在向auto_increment列表插入数据时相关锁的行为以及主从数据一致性的平衡。

1.1 插入(INSERT LIKE)的分类

1.1.1. Simple inserts(简单插入)

是可以预先确定将要插入行数的insert语句,包括单行和多行INSERT语句,例如INSERT, INSERT … VALUES(),VALUES()语法。

1.1.2. Bulk inserts(大量插入)

事先不知道要插入的行数的语句,包括INSERT ... SELECTREPLACE ... SELECTLOAD DATA语句,但不是纯INSERT,每处理一行时,一次为一列分配新增的AUTO_INCRMENT

1.1.3. Mixed inserts(混合模式插入)

  • 一些特殊的“简单插入”语句,用于指定部分(但不是全部)新行的自动增量值,例如INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');
  • 例如INSERT … ON DUPLICATE KEY UPDATE,在最坏的情况下实际上是INSERT紧跟着UPDATE,其中AUTO_INCREMENT在更新阶段可能会或者不会使用为列分配的值。

1.2 innodb_autoinc_lock_mode配置

1.2.1. 版本更新:

  • 在mysql5.1.22版本之前,是不支持innodb_autoinc_lock_mode配置的。
  • 在mysql8.0之前,默认innodb_autoinc_lock_mode=1,即连续锁定模式。
  • 在mysql8.0开始,默认innodb_autoinc_lock_mode=2,即交错锁定模式。

因为Mysql8.0之前,备份(binlog)默认是基于语句(statement模式)的复制。而Mysql8.0开始,binlog默认是基于行(row模式)的复制。

基于语句的复制需要连续的自动增量锁定模式,以确保为给定的SQL语句序列以可预测和可重复的顺序分配自动增长值。而基于行的复制对SQL语句的执行顺序不敏感。

1.2.2. 配置详情

innodb_autoinc_lock_mode = 0 (“ 传统 ”锁定模式)

该模式是Mysql5.1之前未引入innodb_autoinc_lock_mode配置参数时的行为,提供了传统的锁定模式选项以实现向后兼容。

在这种模式下,所有INSERT语句(INSERT LIKE)都会获得特殊的表级AUTO-INC锁定,将其插入具有AUTO_INCREMENT列的表中。此锁定通常保持在语句的末尾(而不是事务的末尾)。

举例分析:假设有两个事务正在运行,每个事务都将行插入具有AUTO_INCREMENT列的表中。一个事务使用insert ... select插入1000行的语句,另一事务使用insert插入一个行的简单语句:

Tx1: INSERT INTO t1 (c2) SELECT 1000 rows from another table ...
Tx2: INSERT INTO t1 (c2) VALUES ('xxx');

InooDB无法预先判断Tx1会插入多少行,Tx1使用表级锁(保持在该语句的末尾)去阻塞Tx2的并发执行,Tx1每次插入时均分配一个自增id,最终t1语句生成的递增主键是连续的。在主从复制或者故障恢复时,若binlog使用statement模式(基于语句的复制),主从服务器执行insert语句得到的结果是完全相同的。

innodb_autoinc_lock_mode = 1 (“ 连续 ”锁定模式)

Mysql5.1.2-Mysql8.0innodb_autoinc_lock_mode的默认配置。

  • simple inserts:直接通过分析语句,获取要插入的的数量,然后一次性分配足够的auto_increment id,只会将整个分配过程锁住。
  • Bulk inserts:[[bʌlk]]因为不能确定插入的数量,因此还会将表锁住;
  • Mixed-mode inserts:直接分析语句,获取最坏情况下需要插入的数量,然后一次性分配足够的auto increment id,只会将整个分配过程锁住。

innodb_autoinc_lock_mode = 2 (“交叉”锁定模式)

这种模式下插入语句(INSERT LIKE)来一个分配一个,而不会锁表,只会锁住分配ID的过程,和innodb_autoinc_lock_mode = 1区别bulk insert是不会预分配多个,这种方式的并发性最高。

若是binlog的模式为statement模式,由于并发情况下Bulk inserts在分配的时会同时向其他insert分配,会出现主从不一致的情况。

所以需要配合binlogrow模式使用。

2. InnoDB的自增主键特性

  1. 主从复制下锁定策略

如果binlog为statement模式(基于语句的复制),请将innodb_autoinc_lock_mode设置为0或1,并在主设备及从设备上使用相同的值。
如果binlog是row模式或者mixed模式,则innodb_autoinc_lock_mode均是安全的。因为基于行的复制对于SQL语句的执行顺序不敏感。

  1. “丢失”自增值和序列间隙

在所有锁定模式(0,1和2)中,如果生成自增值的事务回滚,则这些自增值将“丢失”。为自动递增列生成值后,无论“INSERT like”语句是否完成,以及包含的事务是否回滚,都无法回滚该值。这样丢失的值不会被重用。因此,自增列中的值有间隙。

  1. 自增列上的NULL和0

在所有锁模式(0,1和2)中,如果用户未INSERT中的AUTO_INCREMENT列指定NULL或0,InnoDB会将该行视为未指定值并为其生成新值。

  1. 为自动递增列指定负值

在所有锁定模式(0,1和2)中,如果为“auto_increment”列指定负值,则自增特性不会生效(持久化的为负值)。

  1. “大量插入(bulk inserts)”下自增列与间隙

当innodb_autoinc_lockm_mode设置为0或1时,任何给定语句生成的自增值都是连续的,没有间隙。因为会使用表锁一直到语句结束,并且一次只能执行一个这样的语句。

在innodb_autoinc_lockm_mode=2的情况下,在“bulk inserts”并发执行时,生成的自增列可能存在间隙。

6. 更新自增列的值

第一步:插入数据(0和null会执行自增策略)

create table t(x int auto_increment not null primary key);
insert into t(x) values(0),(null),(3);
select * from t;
+---+
| x |
+---+
| 1 |
| 2 |
| 3 |
+---+

第二步:修改sql中的自增列。

update t set x=4 where x=1;
select * from t;
+---+
| x |
+---+
| 2 |
| 3 |
| 4 |
+---+

第三步:再次插入

insert into t(x) values(0);
ERROR 1062 (23000): Duplicate entry '4' for key 'PRIMARY'

第四步:分析

执行完第一步后,mysql的自增序列生成器知道下一个自增值为4;

执行第二步,mysql并不知道自增列4已经被人占用,所以执行第三步的时候就出现异常。

官方文档

官方文档—InnoDB中的AUTO_INCREMENT处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容