|||
自增实际上是单个表上的一个计数器,对于简单的insert语句来讲肯定都是每次+1的,但是对于批量就有可能预先分配一些。一旦抬升不会因为错误或者回滚而降低,简单总结一下常见的情况,
<code class="language-js_darkmode__7">| 1198 | g | | 1199 | g | | 1200 | g | ->gap | 1256 | g | ->gap | 1257 | g |
大概的算法为第一次申请1个,第二次申请2个,第三次申请4个 ...每次为2的N次方,但是每次分配不能超过AUTO_INC_DEFAULT_NB_MAX(65535),也就是最大一次分配65535个自增。代码如下,
nb_desired_values = AUTO_INC_DEFAULT_NB_ROWS * (1 << auto_inc_intervals_count);//每次左移1位,也就是2的auto_inc_intervals_count次方
nb_desired_values = std::min(nb_desired_values, ulonglong(AUTO_INC_DEFAULT_NB_MAX));
但是值得注意的是,如果有大量insert on duplicate key update的语法,这种语法当插入唯一值的时候在本应该报错唯一键冲突的时候屏蔽报错,转走update流程,但是实际上报错是存在的因此自增也随之提升,当执行下一次插入的时候就会由于自增已经提升而导致很多无谓的gap,这实际上就是第2点。 replace语法也有类似的问题,replace的问题在于会如果触发update机会修改主键自增的值,导致gap。下面是insert on duplicate key update的测试(8.0版本),
<code class="language-js_darkmode__13">mysql> show create table test123 \G *************************** 1. row *************************** Table: test123 Create Table: CREATE TABLE `test123` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, `a` int DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `a` (`a`) ) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 1 row in set (0.00 sec) mysql> insert into test123(name,a) values('g',1); Query OK, 1 row affected (0.03 sec) mysql> insert into test123(name,a) values('g',2); Query OK, 1 row affected (0.01 sec) mysql> insert into test123(name,a) values('g',3); Query OK, 1 row affected (0.00 sec) mysql> insert into test123(name,a) values('g',4); Query OK, 1 row affected (0.05 sec) mysql> insert into test123(name,a) values('g',5); Query OK, 1 row affected (0.00 sec) mysql> insert into test123(name,a) values('g',6); Query OK, 1 row affected (0.01 sec) mysql> insert into test123(name,a) values('g',7); Query OK, 1 row affected (0.00 sec) mysql> select * from test123; +-----+------+------+ | id | name | a | +-----+------+------+ | 120 | g | 1 | | 121 | g | 2 | | 122 | g | 3 | | 123 | g | 4 | | 124 | g | 5 | | 125 | g | 6 | | 126 | g | 7 | +-----+------+------+ 7 rows in set (0.00 sec) mysql> insert into test123(name,a) values('g',1) on duplicate key update name='g'; Query OK, 0 rows affected (0.01 sec) mysql> insert into test123(name,a) values('g',1) on duplicate key update name='g'; Query OK, 0 rows affected (0.00 sec) mysql> insert into test123(name,a) values('g',1) on duplicate key update name='g'; Query OK, 0 rows affected (0.01 sec) mysql> insert into test123(name,a) values('g',1) on duplicate key update name='g'; Query OK, 0 rows affected (0.00 sec) mysql> insert into test123(name,a) values('g',1) on duplicate key update name='g'; Query OK, 0 rows affected (0.01 sec) mysql> select * from test123; +-----+------+------+ | id | name | a | +-----+------+------+ | 120 | g | 1 | | 121 | g | 2 | | 122 | g | 3 | | 123 | g | 4 | | 124 | g | 5 | | 125 | g | 6 | | 126 | g | 7 | +-----+------+------+ 7 rows in set (0.00 sec) 这里数据虽然没有变化但是自增最大值变了,再次插入一条数据如下, mysql> insert into test123(name,a) values('g',8); Query OK, 1 row affected (0.00 sec) mysql> select *from test123; +-----+------+------+ | id | name | a | +-----+------+------+ | 120 | g | 1 | | 121 | g | 2 | | 122 | g | 3 | | 123 | g | 4 | | 124 | g | 5 | | 125 | g | 6 | | 126 | g | 7 | ->gap | 132 | g | 8 | ->gap +-----+------+------+ 8 rows in set (0.00 sec)
可以看到 126和132之间的自增就丢失了。
合作电话:010-64087828
社区邮箱:greatsql@greatdb.com