MySQL。为什么我的INSERT语句在自动递增id时跳过了56个数字?

问题描述 投票:1回答:1

在给我的SQL课程的学生演示INSERT语句时,我们发现MySQL 8.0中出现了一些奇怪的行为。请帮助我们了解发生了什么。(不需要变通的方法,因为我们知道一些,而且这是为了学习,不是为了生产。(不需要变通的方法,因为我们知道一些,这是为了学习,而不是为了生产,谢谢你)

我们正在创建一个新的数据库,并从著名的 Sakila 样的DB,像这样。

CREATE DATABASE simpsons;

USE simpsons;

CREATE TABLE `character` (
    character_id smallint unsigned NOT NULL AUTO_INCREMENT,
    first_name VARCHAR(20) NOT NULL,
    last_name VARCHAR(20),
    shoe_size INT,
    PRIMARY KEY (character_id));

INSERT INTO `character` 
        (first_name, last_name)
    SELECT 
        first_name, last_name 
    FROM 
        sakila.actor;

当我们这样做的时候 SELECT * FROM ``character`` 我们看到,所有200条记录从 sakila.actor 已被正确复制到新的 character 表。

最后一行得到的值是 200 因其 character_id 自动增量PK。输出窗口显示上述命令都没有错误。

然后,当我们立即再手动添加一条记录。

INSERT INTO `character`
    (first_name, last_name, shoe_size)
VALUES
    ('Bart', 'Simpson', 35);

很奇怪的是,我们发现这个记录得到的值是: 256 作为其 character_id 而不是 201.

尽管事实是,运行 SHOW VARIABLES LIKE 'auto_inc%'; 显示,这两个 auto_increment_incrementauto_increment_offset 被设定为 1.

我们想了解 何以 MySQL是否跳过56个数字?


请注意,这个问题不同于 MySQL InnoDB auto_increment值增加2而不是1,病毒?MySQL自动增加列跳动10-为什么? 因为 auto_incerement_increment 是1,在我们的(容易重现的)方案中没有DELETE操作,我们每个人都是我们未来DB的唯一用户。另外,这个问题的答案都不能确定实际发生了什么。最后,请看 @Postman 的精彩回答,其中提到了上述问题的任何答案中都没有提到的根本原因。谢谢你的回答

mysql auto-increment
1个回答
3
投票

这种行为与以下几点有关 "批量插入"innodb_autoinc_lock_mode 设置。

根据我的理解(文档对此不太清楚),当你使用一个 INSERT INTO ... SELECT 语句,MySQL在运行查询前无法知道实际插入了多少行,但在使用新的AUTO_INCREMENT值的ID时必须保留 innodb_autoinc_lock_mode=1 (连续)或 2 交错的)。根据我的观察,它保留了一组AUTO_INCREMENT的数字,其中计数是2的幂数(无法确认,只能猜测)。请看下面的例子。

CREATE TABLE sourceTable(
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(20)
);

CREATE TABLE targetTable(
    id INT AUTO_INCREMENT PRIMARY KEY,
    original VARCHAR(30)
);

INSERT INTO sourceTable(name) VALUES ('one');
INSERT INTO sourceTable(name) VALUES ('two');
INSERT INTO sourceTable(name) VALUES ('three');
INSERT INTO sourceTable(name) VALUES ('four');
INSERT INTO sourceTable(name) VALUES ('five');

INSERT INTO targetTable(original) SELECT name FROM sourceTable;

INSERT INTO targetTable(original) VALUES ('manual');

SELECT * FROM targetTable;

这将产生以下的输出:

+----+----------+
| id | original |
+----+----------+
|  1 | one      |
|  2 | two      |
|  3 | three    |
|  4 | four     |
|  5 | five     |
|  8 | manual   |
+----+----------+

当从源表中插入5条记录时,它保留了接下来的8个可能的AUTO_INCREMENT值,因为那是最接近大于5的2次幂的数字。 然而,由于你只插入了5条记录,所以它将只使用其中的5条。

在你的例子中,你插入了200条记录,所以大于200的2的最接近的幂数是256。所以你有一个56个缺失的AUTO_INCREMENT值的 "空隙",而下一个条目的ID为256。

© www.soinside.com 2019 - 2024. All rights reserved.