为什么INNODB批量插入导致自动增量主键跳过值?

时间:2012-01-24 16:26:07

标签: mysql sql innodb

我很熟悉InnoDB中插入失败导致自动递增主键的间隙,我相信这是无关的(这对我来说并不明显)。我遇到的问题是我将使用自动递增的主键将5条记录插入到表中,这会导致主键的间隔为5到8.这是一个重复问题的脚本。

DROP TABLE IF EXISTS `test_table`;
CREATE TABLE `test_table` (
`A` int(10) unsigned NOT NULL AUTO_INCREMENT,
`B` int(10) unsigned NOT NULL,
PRIMARY KEY (`A`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

insert into `test_table` (`B`)
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5;

insert into `test_table` (`B`)
SELECT 6
UNION
SELECT 7
UNION
SELECT 8
UNION
SELECT 9
UNION
SELECT 10;

SELECT * FROM `test_table`;

在这种情况下,我希望A列和B列都相同,但在第二次插入A的开头A将是8,而B将是6.有谁知道为什么会出现这种差距?

我看过这里的文档:http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html但这些锁定模式似乎与这个差距无关(我可能会遗漏一些东西)。

2 个答案:

答案 0 :(得分:4)

出于某种原因'INSERT INTO test_tableB)SELECT 1 UNION SELECT 2'设置AUTO_INCREMENT = 4,但这会按预期插入工作 -

INSERT INTO `test_table` (`B`)
VALUES (1), (2), (3), (4), (5);

INSERT INTO `test_table` (`B`)
VALUES (6), (7), (8), (9), (10);

尝试设置innodb_autoinc_lock_mode = 0并再次运行脚本,不会有间隙。

AUTO_INCREMENT Handling in InnoDB

答案 1 :(得分:1)

我认为查询分析器被要求粗略估计内部查询将返回多少行,并且稍微关闭。

数据库引擎需要争取三个相互冲突的目标:

  • 事务需要是原子的,因此从事务中的序列生成的任何数字都必须是连续的。
  • 序列不应该长时间锁定(否则,其他INSERT操作将被阻止),
  • 内部查询不需要实现完整的结果表,因为它可能相当大。

由于没有人保证序列号全局连续,最好的方法是获得必须插入的行数的上限,然后按顺序递增序列(原子地)并使用如此保留的块INSERT操作。

这可以保证并发INSERT将具有更小或更大的主键值(即查询被正确序列化),但是可以在行之间添加数据(因为除非使用ORDER BY子句,否则没有排序)