1、语句执行过程中 , 第一次申请自增 id,会分配 1 个;
2、1 个用完以后 , 这个语句第二次申请自增 id,会分配 2 个;
3、2 个用完以后,还是这个语句,第三次申请自增 id , 会分配 4 个;
4、依此类推,同一个语句去申请自增 id,每次申请到的自增 id 个数都是上一次的两倍 。
执行以下SQL语句(在表t中先新增了4条数据,在创建表tt把表t数据进行批量新增)
insert into t values(null, 1,1);
insert into t values(null, 2,2);
insert into t values(null, 3,3);
insert into t values(null, 4,4);
create table tt like t;
insert into tt(c,d) select c,d from t;
insert into tt values(null, 5,5);
第一次申请到了 id=1,第二次被分配了 id=2 和 id=3 , 第三次被分配到 id=4 到 id=7 。当我们再执行 insert into t2 values(null, 5,5),实际上插入的数据就是(8,5,5),出现了自增主键不连续的情况 。

文章插图
六、自增主键值的优化
1.什么是自增锁
自增锁是一种比拟非凡的表级锁 。并且在事务向蕴含了 AUTO_INCREMENT 列的表中新增数据时就会去持有自增锁,假如事务 A 正在做这个操作 , 如果另一个事务 B 尝试执行 INSERT语句,事务 B 会被阻塞住,直到事务 A 开释自增锁 。
2.自增锁有哪些优化
在 MySQL 5.0 版本的时候 , 自增锁的范围是语句级别 。也就是说,如果一个语句申请了一个表自增锁,这个锁会等语句执行结束以后才释放 。显然 , 这样设计会影响并发度 。在MySQL 5.1.22 版本引入了一个新策略 , 新增参数 innodb_autoinc_lock_mode,默认值是 1 。
传统模式(Traditional)
这个参数的值被设置为 0 时,表示采用之前 MySQL 5.0 版本的策略,即语句执行结束后才释放锁;
传统模式他可以保证数据一致性,但是如果有多个事务并发的执行 INSERT 操作 , AUTO-INC的存在会使得 MySQL 的性能略有降落 , 因为同时只能执行一条 INSERT 语句 。
间断模式(Consecutive)
这个参数的值被设置为 1 时:普通 insert 语句 , 自增锁在申请之后就马上释放;类似 insert … select 这样的批量插入数据的语句,自增锁还是要等语句结束后才被释放;
【MySQL自增主键一定是连续的吗?】间断模式他可以保证数据一致性,但是如果有多个事务并发的执行 INSERT 批量操作时 , 就会进行锁等待状态 。如果我们业务插入数据量很大时,这个时候MySQL的性能就会大大下降 。
穿插模式(Interleaved)
这个参数的值被设置为 2 时,所有的申请自增主键的动作都是申请后就释放锁 。
穿插模式他没有进行任何的上锁设置 。在一定情况下是保证了MySQL的性能 , 但是他无法保证数据的一致性 。如果我们在穿插模式下进行主从复制时,如果你的binlog格式不是row格式,主从复制就会出现不一致 。具体可以了解一下我的这篇文章MySQL是如何保证主从一致
七、MySQL8.0做了哪些优化
在MySQL8.0之后版本 , 已经默认设置为 innodb_autoinc_lock_mode=2,binlog_format=row. 。这样更有利与我们在 insert … select 这种批量插入数据的场景时,既能提升并发性,又不会出现数据一致性问题 。
作者丨又 欠
来源丨https://blog.csdn.NET/qq_48157004/article/detAIls/128356734
推荐阅读
- 怎么进入mysql日志 mysql登录日志文件在哪
- MySQL误删数据怎么办?
- 为什么MySQL默认使用RR隔离级别?
- MySQL 核心模块揭秘
- MySQL 核心模块揭秘,你看明白了吗?
- 从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
- 准线上事故之MySQL优化器索引选错
- MySQL数据恢复,你会吗?
- 如何在MySQL中实现数据的版本管理和回滚操作?
- 为什么高性能场景选用Postgres SQL 而不是 MySQL
