以下是使用默认设置
innodb_autoinc_lock_mode
= 1(“连续”锁模式)时的行为表现。请参考名为
InnoDB中的AUTO_INCREMENT处理 的详细手册页面。将此值更改为“传统”锁定模式下的设置= 0将降低并发性和性能,因为它使用表级别的AUTO-INC锁定。
尽管如此,默认设置= 1的以下内容也说明了创建间隔有多容易。
示例1:
create table x
( id int auto_increment primary key,
someOtherUniqueKey varchar(50) not null,
touched int not null,
unique key(someOtherUniqueKey)
);
insert x(touched,someOtherUniqueKey) values (1,'dog') on duplicate key update touched=touched+1;
insert x(touched,someOtherUniqueKey) values (1,'dog') on duplicate key update touched=touched+1;
insert x(touched,someOtherUniqueKey) values (1,'cat') on duplicate key update touched=touched+1;
select * from x;
+
| id | someOtherUniqueKey | touched |
+
| 1 | dog | 2 |
| 3 | cat | 1 |
+
由于INNODB引擎的一些操作、怪癖和紧张的抽搐,间隙(id=2被跳过)会出现。在其默认的高并发性能模式下,它为发送给它的各种查询执行范围间隙分配。除非你有充分的理由更改此设置,否则这样做会影响性能。MySQL的后续版本提供了您需要的功能,并且您可以关闭它们以便专注于打印纸张上的空隙(以及那些说“我们为什么有空隙”的老板)。
在插入重复键更新(IODKU)的情况下,它假定有1行新数据并为其分配一个插槽。请记住,这是并发操作,而且您的同行也可能同时进行数百个操作。当IODKU变成更新时,那么您的连接和其他人使用的ID为2的未使用和未插入的行就没用了。
在“Insert ... Select From”中也会发生同样的事情,如我在
这个答案中所示。在此答案中,我故意使用MyISAM进行报告计数、最小值、最大值,否则范围间隙怪癖将分配但不填充所有内容。而且数字看起来很奇怪,因为该答案涉及实际数字。所以旧的引擎(MyISAM)对于没有间隙的紧密情况工作得很好。请注意,在那个答案中,我试图做一些快速而安全的事情,并且可以在事后使用ALTER TABLE将表转换为INNODB。如果我一开始就在INNODB中完成了这个示例,那么默认模式下会有大量的间隙。如果我在“Insert ... Select From”中使用INNODB,那么会在答案中创建间隙是由于计数的不确定性和引擎选择用于安全(不确定)范围分配的机制。INNODB引擎自然知道操作,知道它必须创建一个安全的AUTO_INCREMENT ID池,具有并发性(需要考虑其他用户),并且间隙繁荣。这是一个事实。尝试使用INNODB引擎进行示例2,看看你能得到什么样的最小值、最大值和计数。最大值将不等于计数。
Percona网站记录了导致INNODB间隙的各种情况,例如在
1452错误图像中看到的由于外键约束而导致的插入失败,或者在
1062错误图像中的主键错误。
请记住,INNODB
间隙是系统性能和安全引擎的副作用。一个人真的想关闭它(性能、更高的用户满意度、更高的并发性、缺少表锁),为了更紧密的ID范围?在删除时也会留下空洞。对于我的实现,我建议不要关闭它,并且默认设置与性能相当好。
sID
列,然后您可以找到最大值,再加1以用于最新插入。 (您可能可以在SQL查询中自动执行此操作) - Martin