MySQL AUTO_INCREMENT 学习总结
正文
之前有碰到过开发同事指出一张innodb表的自增列 auto_increment 值莫明的变大,由于这张表是通过mysqldump导出导入的。
问题排查:
1、首先,查看表表义的sql部分的 auto_increment 值部分是正常,所以排除是导入表问题所引起的;
2、最后,经过沟通了解怀疑是插入时指定自增列的值,并且值过大,随之发现自增列的值出错时又进行大量删除时引起的问题。
为了验证这个怀疑的准确性,同时学习下innodb处理 auto_increment 的机制,因此在测试环境做了测试总结。
本文使用的mysql版本为官方社区版 5.7.24
。
(root@localhost) [test] > select version(); +------------+ | version() | +------------+ | 5.7.24-log | +------------+ 1 row in set (0.00 sec)
测试环境测试表参考官方文档:
(root@localhost) [test] > show create table t1\g; *************************** 1. row *************************** table: t1 create table: create table `t1` ( `c1` int(11) not null auto_increment, `c2` varchar(10) default null, primary key (`c1`) ) engine=innodb default charset=utf8 1 row in set (0.00 sec) (root@localhost) [test] > show columns from t1; +-------+-------------+------+-----+---------+----------------+ | field | type | null | key | default | extra | +-------+-------------+------+-----+---------+----------------+ | c1 | int(11) | no | pri | null | auto_increment | | c2 | varchar(10) | yes | | null | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)
auto_increment锁模式
innodb自增锁的模式由参数 innodb_autoinc_lock_mode
在启动时指定,这是一个只读参数,并不能在实例运行中动态修改参数值。参数值选项如下:
innodb_autoinc_lock_mode = {0|1|2}
innodb表insert语句主要可以分为三种类型:
simple inserts(简单插入)
可以通过语句预先判断插入的行数。包括不包含子查询的单行、多行 insert 和 replace 语句,还有语句 insert ... on duplicate key update。bulk inserts(大量插入)
无法通过语句预先判断插入的行数。包括 insert ... select 、 replace ... select 和 load data 语句。innodb每处理一行才会为 auto_increment 列分配一个值。mixed-mode inserts(混合模式插入)
在简单插入语句当中,有的行有为自增列指定值,而有的行没有为自增列指定值。例如:
insert into t1 (c1,c2) values (1,'a'), (null,'b'), (5,'c'), (null,'d');
其中c1
为自增列。
还有一种混合模式插入语句 insert ... on duplicate key update ,这类语句innodb为自增列预分配的值有可能被使用,也有可能不被使用。
传统锁模式 (traditional)
innodb_autoinc_lock_mode = 0
在这个模式下,所有的 insert 语句在插入有自增属性的列时都要获取一个特殊的 auto-inc 表级锁。该锁的持有时间到语句结束(而不是到事务结束,一个事务中可能包含多条语句),它能够确保为有自增属性列在 insert 一行或者多行数据时分配连续递增的值。
连续锁模式 (consecutive)
innodb_autoinc_lock_mode = 1
这是默认的锁模式。在这个模式下,大量插入每条语句执行时都将获得特殊的表级 auto-inc 锁,语句执行完成后释放。每次只有一条语句可以执行并持有 auto-inc 锁。
-
bulk inserts(大量插入)
- 如果大量插入的源表和目标表是不同的,则在源表第一行数据获得共享锁之后,目标表就加上 auto-inc 表锁;
- 如果大量插入的源表和目标表是同一张表,当源表选取所有行获得共享锁之后,目标表才加上 auto-inc 表锁。
-
simple inserts(简单插入)
- 通过 mutex(轻量级的锁) 而不是 auto-inc特殊表锁控制插入分配自增属性列的值;
- mutex 只在分配值的过程中持有,而无需等到语句结束,并且性能花销更少;
- 简单插入不持有 auto-inc 锁,但如果其他事务持有,需等待其他事务释放,就像大量插入那样。
交叉锁模式 (interleaved)
innodb_autoinc_lock_mode = 2
在这种锁模式下,没有插入语句使用 auto-inc 表级锁,并且多条语句可以并发执行。这是最快并且扩展性最好的锁模式,但是如果binlog使用基于语句级复制的在从库重放sql语句时是不安全的。
auto_increment锁模式使用说明
用于复制
- 基于语句级别的复制,当 innodb_autoinc_lock_mode = 0 | 1 时,主从使用的是相同的自增列值。当 innodb_autoinc_lock_mode = 2 或者主从使用不同的 innodb_autoinc_lock_mode 时,主从无法保证使用相同的自增列值;
- 基于行级别和复合模式的复制,innodb_autoinc_lock_mode 的所有取值都是安全的,因为sql语句执行顺序对基于行级别的复制没影响。
自增值缺失与间隙
无论 auto_increment 处于哪种锁模式下,即 innodb_autoinc_lock_mode 的所有取值情况下,在一个事务当中自增列分配的值是不能被回滚的。这会导致事务回滚了,但是自增列分配的值却消失了,自增列分配的值是无法随着事务回滚而重复利用,这样就自增列上的值就产生了间隙。
测试:
--1、 开启一个事务 (root@localhost) [test] > begin; query ok, 0 rows affected (0.00 sec) (root@localhost) [test] > insert into t1(c2) values('aa'); query ok, 1 row affected (0.00 sec) (root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | 1 | aa | +----+------+ 1 row in set (0.00 sec) (root@localhost) [test] > show create table t1\g; *************************** 1. row *************************** table: t1 create table: create table `t1` ( `c1` int(11) not null auto_increment, `c2` varchar(10) default null, primary key (`c1`) ) engine=innodb auto_increment=2 default charset=utf8 1 row in set (0.00 sec) --2、事务回滚,不提交 (root@localhost) [test] > rollback; query ok, 0 rows affected (0.00 sec) (root@localhost) [test] > select * from t1; empty set (0.00 sec) (root@localhost) [test] > show create table t1\g; *************************** 1. row *************************** table: t1 create table: create table `t1` ( `c1` int(11) not null auto_increment, `c2` varchar(10) default null, primary key (`c1`) ) engine=innodb auto_increment=2 default charset=utf8 1 row in set (0.00 sec) --3、再次开启事务,插入值并提交 (root@localhost) [test] > begin; query ok, 0 rows affected (0.00 sec) (root@localhost) [test] > insert into t1(c2) values('aaa'); query ok, 1 row affected (0.02 sec) (root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | 2 | aaa | +----+------+ 1 row in set (0.00 sec) (root@localhost) [test] > commit; query ok, 0 rows affected (0.00 sec) (root@localhost) [test] > show create table t1\g; *************************** 1. row *************************** table: t1 create table: create table `t1` ( `c1` int(11) not null auto_increment, `c2` varchar(10) default null, primary key (`c1`) ) engine=innodb auto_increment=3 default charset=utf8 1 row in set (0.00 sec)
可以看出自增列分配的值是不会再出现 c1=1 的。
为自增列指定null或者0
无论 auto_increment 处于哪种锁模式下,如果在 insert 语句为自增列指定 null 或者 0 时,innodb认为并没有为自增列指定值,同时也会为其分配值。
测试:
(root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | 2 | aaa | +----+------+ 1 row in set (0.00 sec) (root@localhost) [test] > insert into t1 values(null,'bbb'),(0,'ccc'); query ok, 2 rows affected (0.02 sec) records: 2 duplicates: 0 warnings: 0 (root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | 2 | aaa | | 3 | bbb | | 4 | ccc | +----+------+ 3 rows in set (0.00 sec) (root@localhost) [test] > show create table t1\g; *************************** 1. row *************************** table: t1 create table: create table `t1` ( `c1` int(11) not null auto_increment, `c2` varchar(10) default null, primary key (`c1`) ) engine=innodb auto_increment=5 default charset=utf8 1 row in set (0.00 sec)
为自增列指定负值
无论 auto_increment 处于哪种锁模式下,自增列分配值机制不会生效,即为自增列指定负值是不影响 auto_increment 值的。
测试:
(root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 5 | +----------------+ 1 row in set (0.00 sec) (root@localhost) [test] > insert into t1 values(-1,'ddd'); query ok, 1 row affected (0.01 sec) (root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | -1 | ddd | | 2 | aaa | | 3 | bbb | | 4 | ccc | +----+------+ 4 rows in set (0.00 sec) (root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 5 | +----------------+ 1 row in set (0.00 sec)
自增列值大于列类型最大的整型值
无论 auto_increment 处于哪种锁模式下,自增列分配的值如果大于自增列所属字段类型的最大值,则自增列分配值机制就不会生效。
测试:
在mysql当中,int类型的最大值为 -2147483648~2147483647
(root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | -1 | ddd | | 2 | aaa | | 3 | bbb | | 4 | ccc | +----+------+ 4 rows in set (0.00 sec) (root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 5 | +----------------+ 1 row in set (0.00 sec) (root@localhost) [test] > insert into t1 values(2147483647,'eee'); query ok, 1 row affected (0.02 sec) (root@localhost) [test] > select * from t1; +------------+------+ | c1 | c2 | +------------+------+ | -1 | ddd | | 2 | aaa | | 3 | bbb | | 4 | ccc | | 2147483647 | eee | +------------+------+ 5 rows in set (0.00 sec) (root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 2147483647 | +----------------+ 1 row in set (0.00 sec)
可以看出自增列 auto_increment 并不会分配。
大量插入导致的间隙
- 当参数值 innodb_autoinc_lock_mode 设置为 0 或 1 时,每条语句生成的自增列值都是连续的,不会产生间隙。因为表级 auto-inc 锁会一直持有直到语句结束,并且同一时间只有一条语句在执行;
- 当参数值 innodb_autoinc_lock_mode 设置为 2 时,在大量插入时有可能会产生间隙,但是只有当并发执行 insert 语句时。
- 对于设置成 1 或者 2 情形下,在连续的语句之间可能产生间隙,因为对于大量插入innodb并不清楚每条语句所需自增量值数量。
混合模式插入自增列值分配
测试表:
-- t1表:表中无数据,但自增列下一个分配值从101开始 (root@localhost) [test] > show create table t1\g; *************************** 1. row *************************** table: t1 create table: create table `t1` ( `c1` int(11) not null auto_increment, `c2` varchar(10) default null, primary key (`c1`) ) engine=innodb auto_increment=101 default charset=utf8 1 row in set (0.00 sec) (root@localhost) [test] > select count(*) from t1; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec) -- t2表:表中有100万行数据,并且自增列值是连续的 (root@localhost) [test] > show create table t2\g; *************************** 1. row *************************** table: t2 create table: create table `t2` ( `c1` int(11) not null auto_increment, `c2` varchar(10) default null, primary key (`c1`) ) engine=innodb auto_increment=1000001 default charset=utf8 1 row in set (0.00 sec) (root@localhost) [test] > select count(*) from t2; +----------+ | count(*) | +----------+ | 1000000 | +----------+ 1 row in set (0.22 sec) (root@localhost) [test] > select min(c1),max(c1) from t2; +---------+---------+ | min(c1) | max(c1) | +---------+---------+ | 1 | 1000000 | +---------+---------+ 1 row in set (0.01 sec)
innodb_autoinc_lock_mode = 0
(root@localhost) [test] > show global variables like 'innodb_autoinc_lock_mode'; +--------------------------+-------+ | variable_name | value | +--------------------------+-------+ | innodb_autoinc_lock_mode | 0 | +--------------------------+-------+ 1 row in set (0.02 sec) -- 1、开启session 1执行trx1 trx1: insert into t1(c2) select c2 from t2; (root@localhost) [test] > insert into t1(c2) select c2 from t2; query ok, 1000000 rows affected (6.37 sec) records: 1000000 duplicates: 0 warnings: 0 -- 2、在trx1执行期间开启session 2执行trx2 trx2: insert into t1 (c1,c2) values (1,'test_inc_a'), (null,'test_inc_b'), (5,'test_inc_c'), (0,'test_inc_d'); (root@localhost) [test] > insert into t1 (c1,c2) values (1,'test_inc_a'), (null,'test_inc_b'), (5,'test_inc_c'), (0,'test_inc_d'); query ok, 4 rows affected (5.01 sec) records: 4 duplicates: 0 warnings: 0 -- 3、查看trx2插入值的记录 (root@localhost) [test] > select * from t1 where c2 in ('test_inc_a','test_inc_b','test_inc_c','test_inc_d'); +---------+------------+ | c1 | c2 | +---------+------------+ | 1 | test_inc_a | | 5 | test_inc_c | | 1000101 | test_inc_b | | 1000102 | test_inc_d | +---------+------------+ 4 rows in set (0.34 sec) -- 4、查看当前auto_increment值 (root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 1000103 | +----------------+ 1 row in set (0.00 sec)
- trx1:持有了 auto-inc 表锁,自动分配了101~1000100的自增值,并保证是连续的;
- trx2:需等待 auto-inc 锁的释放,自动分配了1000101~1000102的自增值。
可以看出下一个自增列值为 103,因为自增列的值是在每条插入语句执行时分配的,而不是一开始就分配完的。
innodb_autoinc_lock_mode = 1
(root@localhost) [test] > show global variables like 'innodb_autoinc_lock_mode'; +--------------------------+-------+ | variable_name | value | +--------------------------+-------+ | innodb_autoinc_lock_mode | 1 | +--------------------------+-------+ 1 row in set (0.01 sec) -- 1、开启session 1执行trx1 trx1: insert into t1(c2) select c2 from t2; (root@localhost) [test] > insert into t1(c2) select c2 from t2; query ok, 1000000 rows affected (5.88 sec) records: 1000000 duplicates: 0 warnings: 0 -- 2、在trx1执行期间开启session 2执行trx2 trx2: insert into t1 (c1,c2) values (1,'test_inc_a'), (null,'test_inc_b'), (5,'test_inc_c'), (0,'test_inc_d'); (root@localhost) [test] > insert into t1 (c1,c2) values (1,'test_inc_a'), (null,'test_inc_b'), (5,'test_inc_c'), (0,'test_inc_d'); query ok, 4 rows affected (4.38 sec) records: 4 duplicates: 0 warnings: 0 -- 3、查看trx2插入值的记录 (root@localhost) [test] > select * from t1 where c2 in ('test_inc_a','test_inc_b','test_inc_c','test_inc_d'); +---------+------------+ | c1 | c2 | +---------+------------+ | 1 | test_inc_a | | 5 | test_inc_c | | 1048661 | test_inc_b | | 1048662 | test_inc_d | +---------+------------+ 4 rows in set (0.32 sec) -- 4、查看当前auto_increment值 (root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 1048665 | +----------------+ 1 row in set (0.00 sec) -- 5、查看t1表的前10行记录、后10行记录和总行数 (root@localhost) [test] > select * from t1 order by c1 asc limit 10; +-----+------------+ | c1 | c2 | +-----+------------+ | 1 | test_inc_a | | 5 | test_inc_c | | 101 | cwakhbews | | 102 | re | | 103 | uqrqbj | | 104 | sq | | 105 | ojypkma | | 106 | 03qnqz | | 107 | g8j | | 108 | uo3 | +-----+------------+ 10 rows in set (0.00 sec) (root@localhost) [test] > select * from t1 order by c1 asc limit 999994,10; +---------+------------+ | c1 | c2 | +---------+------------+ | 1000093 | o4azur | | 1000094 | njmjjk | | 1000095 | 0o5xpudne | | 1000096 | qlltimqc | | 1000097 | n1fojm | | 1000098 | 6azemarpc | | 1000099 | 4ougsm1jzl | | 1000100 | l8g6j | | 1048661 | test_inc_b | | 1048662 | test_inc_d | +---------+------------+ 10 rows in set (0.32 sec) (root@localhost) [test] > select count(*) from t1; +----------+ | count(*) | +----------+ | 1000004 | +----------+ 1 row in set (0.17 sec)
在此模式下:
- trx1:大量插入时持有 auto-inc 表锁,自增列的值是预先分配的,101~10000100,总共100万个连续值;
- trx2:混合插入情况下,语句为简单 insert 语句,有的行自增列有指定值,而有的行没有,这时trx2是无须等待持有 auto-inc 锁的,由于trx1语句还在执行,innodb并不知道需要分配多少个自增列值,也不清楚trx用了多少个自增列值,所以在并行执行 insert 时对于未指定行的自增列值分配就会产生间隙(1000100~1048661之间的间隙),但是语句当中分配的自增列(1048661和1048662)值依然是连续的。
可以看出下一个自增列值为 1048665 ,因为自增列值个数在语句执行开始就已经分配了4个(1048661~1048664),但实际语句只使用了2个。
innodb_autoinc_lock_mode = 2
(root@localhost) [test] > show global variables like 'innodb_autoinc_lock_mode'; +--------------------------+-------+ | variable_name | value | +--------------------------+-------+ | innodb_autoinc_lock_mode | 2 | +--------------------------+-------+ 1 row in set (0.01 sec) -- 1、开启session 1执行trx1 trx1: insert into t1(c2) select c2 from t2; (root@localhost) [test] > insert into t1(c2) select c2 from t2; query ok, 1000000 rows affected (4.67 sec) records: 1000000 duplicates: 0 warnings: 0 -- 2、在trx1执行期间开启session 2执行trx2 trx2: insert into t1 (c1,c2) values (1,'test_inc_a'), (null,'test_inc_b'), (5,'test_inc_c'), (0,'test_inc_d'); (root@localhost) [test] > insert into t1 (c1,c2) values (1,'test_inc_a'), (null,'test_inc_b'), (5,'test_inc_c'), (0,'test_inc_d'); query ok, 4 rows affected (0.02 sec) records: 4 duplicates: 0 warnings: 0 -- 3、查看trx2插入值的记录 (root@localhost) [test] > select * from t1 where c2 in ('test_inc_a','test_inc_b','test_inc_c','test_inc_d'); +--------+------------+ | c1 | c2 | +--------+------------+ | 1 | test_inc_a | | 5 | test_inc_c | | 262241 | test_inc_b | | 262242 | test_inc_d | +--------+------------+ 4 rows in set (0.28 sec) -- 4、查看当前auto_increment值 (root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 1048665 | +----------------+ 1 row in set (0.00 sec) -- 5、查看t1表的前10行记录、后10行记录和总行数 (root@localhost) [test] > select * from t1 order by c1 asc limit 10; +-----+------------+ | c1 | c2 | +-----+------------+ | 1 | test_inc_a | | 5 | test_inc_c | | 101 | cwakhbews | | 102 | re | | 103 | uqrqbj | | 104 | sq | | 105 | ojypkma | | 106 | 03qnqz | | 107 | g8j | | 108 | uo3 | +-----+------------+ 10 rows in set (0.00 sec) (root@localhost) [test] > select * from t1 order by c1 asc limit 999994,10; +---------+------------+ | c1 | c2 | +---------+------------+ | 1000095 | khukb | | 1000096 | bnpyaevl79 | | 1000097 | o4azur | | 1000098 | njmjjk | | 1000099 | 0o5xpudne | | 1000100 | qlltimqc | | 1000101 | n1fojm | | 1000102 | 6azemarpc | | 1000103 | 4ougsm1jzl | | 1000104 | l8g6j | +---------+------------+ 10 rows in set (0.22 sec) (root@localhost) [test] > select count(*) from t1; +----------+ | count(*) | +----------+ | 1000004 | +----------+ 1 row in set (0.17 sec) -- 6、查看trx2插入时产生间隙位置行记录 (root@localhost) [test] > select * from t1 where c1 between 262240 and 262250; +--------+------------+ | c1 | c2 | +--------+------------+ | 262240 | mnfx37 | | 262241 | test_inc_b | | 262242 | test_inc_d | | 262245 | taqi | | 262246 | ojpakez | | 262247 | 2fktmm6rw | | 262248 | ayse | | 262249 | wqwgs | | 262250 | lc | +--------+------------+ 9 rows in set (0.00 sec)
在此模式下:
- trx1:因为大量插入时是不持有 auto-inc 表锁,所在trx1在执行期间,trx2很快就插入完成并分配了自增列值。
- trx2:简单插入语句时可以判断出须分配4个自增列值,但是只使用了2个,这样就造成了2个间隙(262243~262244)。
可以看出下一个自增列值为 1048665 ,trx1执行时因为大量插入时无法预估插入值数量,trx2执行时分配了4个自增值,但只使用了2个(262241~262242),造成了2个间隙,trx1和trx2的自增列值是交叉分配的。
修改自增列当中的值
无论 auto_increment 处于哪种锁模式下,更新自增列的值都有可能会产生 duplicate entry 重复值错误。
-- 测试表: (root@localhost) [test] > create table t3 (c1 int not null auto_increment primary key); query ok, 0 rows affected (0.06 sec) (root@localhost) [test] > show create table t3\g; *************************** 1. row *************************** table: t3 create table: create table `t3` ( `c1` int(11) not null auto_increment, primary key (`c1`) ) engine=innodb default charset=utf8 1 row in set (0.00 sec) -- 1、插入几行数据 (root@localhost) [test] > insert into t3 values(0),(0),(3); query ok, 3 rows affected (0.04 sec) records: 3 duplicates: 0 warnings: 0 (root@localhost) [test] > select * from t3; +----+ | c1 | +----+ | 1 | | 2 | | 3 | +----+ 3 rows in set (0.00 sec) (root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t3'; +----------------+ | auto_increment | +----------------+ | 4 | +----------------+ 1 row in set (0.00 sec) -- 2、更新c1值为5 (root@localhost) [test] > update t3 set c1 = 5 where c1 = 3; query ok, 1 row affected (0.03 sec) rows matched: 1 changed: 1 warnings: 0 (root@localhost) [test] > select * from t3; +----+ | c1 | +----+ | 1 | | 2 | | 5 | +----+ 3 rows in set (0.00 sec) (root@localhost) [test] > select auto_increment from information_schema.tables where table_schema='test' and table_name='t3'; +----------------+ | auto_increment | +----------------+ | 4 | +----------------+ 1 row in set (0.00 sec) -- 3、再次插入几行数据 (root@localhost) [test] > insert into t3 values(0),(0),(3); error 1062 (23000): duplicate entry '5' for key 'primary' (root@localhost) [test] > select * from t3; +----+ | c1 | +----+ | 1 | | 2 | | 5 | +----+ 3 rows in set (0.00 sec)
可以看出更新了自增列的值之后产生了 duplicate entry 重复值错误。建议不要更新自增列的值,或是把自增列值更新为大于 auto_increment 的值。
auto_increment计数器的初始化
当为一张innodb表指定自增列时,此时表在数据字典中维护着一个特殊的计数器为自增列分配值,名称为 auto_increment 计数器,这个计数器是存储中内存中,而不是在磁盘上。
当服务器重启之后后,为了初始化 auto_increment 计数器,innodb执行如下等效语句来确定自增列下个需要分配的值:
select max(ai_col) from table_name for update;
默认的,自增列的下一个分配值由以上语句得出的值增加 1 ,这个增加步长由参数 auto_increment_increment 决定。如果是空表,则自增列的下一个分配值为 1 ,这个空表时默认值由参数 auto_increment_offset 决定。
- 当表中指定自增列,如果没有为自增列值指定值,则由计数器分配。如果为自增列指定了值,还是插入指定的值。如果指定插入值大于计数器的值,同时计数器也会跟着调整,这样容易造成间隙。
- 由于计数据器是运行在内存中,所以当服务器重启后,innodb会重新初始化计数器。
- 服务器重启的同时也重置了之前 create table 和 alter table 为表指定的 auto_increment 值,可以再次通过语句进行指定。
参考
☆〖本人水平有限,文中如有错误还请留言批评指正!〗☆