【问题标题】:Why do INNODB bulk inserts cause the auto increment primary key to skip values?为什么 INNODB 批量插入会导致自增主键跳过值?
【发布时间】:2012-01-24 16:26:06
【问题描述】:

我很熟悉 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 为 8,B 为 6。有人知道为什么会出现这种差距吗?

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

【问题讨论】:

    标签: mysql sql innodb


    【解决方案1】:

    由于某种原因,'INSERT INTO test_table (B) 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.

    【讨论】:

      【解决方案2】:

      我认为查询分析器被要求粗略估计内部查询将返回多少行,但结果略有偏差。

      数据库引擎需要为三个相互冲突的目标而努力:

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

      由于没有人保证序列号在全局范围内是连续的,最好的方法是获取必须插入的行数的上限,然后将序列(原子地)增加该数量并使用为INSERT 操作。

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

      【讨论】:

        猜你喜欢
        • 2011-04-03
        • 1970-01-01
        • 2012-12-14
        • 1970-01-01
        • 1970-01-01
        • 2019-04-23
        • 2011-09-02
        • 2015-09-18
        • 1970-01-01
        相关资源
        最近更新 更多