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

2024-02-21

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

我们正在创建一个新数据库并从众所周知的数据库中复制一些行Sakila https://dev.mysql.com/doc/sakila/en/示例数据库,如下所示:

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 table.

最后一行获取值200为其character_id自动递增PK。输出窗口显示上述任何命令都没有错误。

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

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

很奇怪的是,我们发现这条记录得到了值256 as its character_id并不是201.

尽管事实上正在运行SHOW VARIABLES LIKE 'auto_inc%';表明两者auto_increment_increment and auto_increment_offset被设置为1.

我们想学习whyMySQL会跳过56个数字吗?


请注意,这个问题不同于MySQL InnoDB auto_increment 值增加 2 而不是 1。 病毒? https://stackoverflow.com/questions/3590391/mysql-innodb-auto-increment-value-increases-by-2-instead-of-1-virus and MySQL自动增量列跳跃10-为什么? https://stackoverflow.com/questions/206751/mysql-autoincrement-column-jumps-by-10-why因为auto_incerement_increment为 1,在我们的(易于重现的)场景中没有 DELETE 操作,并且我们每个人都是我们预期数据库的唯一用户。另外,这个问题的答案都不能确定到底发生了什么。最后,请参阅@Postman 的精彩答案,其中引用了上述问题的任何答案中未提及的根本原因。谢谢


这种行为与“批量插入” https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html#innodb-auto-increment-lock-modesinnodb_autoinc_lock_mode https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_autoinc_lock_mode环境。

据我了解(文档对此不太清楚),当您使用INSERT INTO ... SELECT语句,MySQL 在运行查询之前无法知道实际插入了多少行,但是在使用时必须保留新 AUTO_INCREMENT 值的 IDinnodb_autoinc_lock_mode=1(连续)或2(交错)。根据我的观察,它保留了一组 AUTO_INCRMENT 数字,其中计数是 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_INCRMENT 值,因为这是大于 5 的最接近的 2 次幂。但是,它只会使用其中的 5 个,因为您只插入 5 行。

在您的例子中,您要插入 200 行,因此大于 200 的最接近的 2 次幂将为 256。因此,您有 56 个缺失 AUTO_INCREMENT 值的“间隙”,下一个条目的 ID 为 256。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL:为什么我的 INSERT 语句在自动递增 id 时会跳过 56 个数字? 的相关文章

  • LEFT JOIN 返回与 INNER JOIN 相同的结果

    我有一张桌子 磨砂膏 里面有 1600 个独特的物品 第二张桌子有100万以上 我运行 INNER JOIN 并获得 65 个匹配项 SELECT a BW Parent Number a Vendor Name b Parent Supp
  • 将数据从 javascript 发送到 mysql 数据库

    我有这个小点击计数器 我想将每次点击都包含在 mysql 表中 有人可以帮忙吗 var count1 0 function countClicks1 count1 count1 1 document getElementById p1 in
  • MySQL更改表,添加具有唯一随机值的列

    我有一个表 我添加了一个名为phone 该表还有一个 id 设置为自动增量的主键 如何将随机值插入到电话列中 该值不会重复 以下 UPDATE 语句确实插入了随机值 但并非所有值都是唯一的 另外 我没有被卖掉 我投了phone字段也正确 但
  • 提高mysql导入速度[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我有一个很大的数据库22GB 我曾经用过进行备份mysqldumpgzip 格式的命令 当我提取 gz 文件时 它会生成 sql文件的
  • 如何在 sqlSave() 命令中跳过主键?

    我正在尝试使用 RODBC 在 MySQL 数据库中插入 data frame 我正在使用的命令如下 sqlSave channel dbData tablename table name append TRUE safer TRUE fa
  • 如何在SQL中查找单元格中的重复单词

    我有一个名为 situation 和 entityid 的列 Entityid Situation 1234 In the the world of of 3456 Total universe is is a 任何人都可以给我查询以找到这
  • 在旧版本的 MySQL (<5.5.0) 中模拟 TO_SECONDS()

    出于性能和简单性的原因 我想以秒的形式获取 MySQL 3 x 服务器中 DATETIME 列的内容 或者实际上任何数字类型 我只是想在使用 UNIX TIMESTAMP 时避免所有明显的时区问题 the我表中的日期确实来自不同的区域设置
  • 启动服务器后,带有sequelize的Nodejs无法在mysql工作台中创建表

    我开始学习如何使用构建 Rest APINodejs Expressjs Sequelize and MySQL using Mysqlworkbench 我的问题 启动服务器后 该表不是由Sequelize并且没有表Mysqlworkbe
  • 是否有工具可以将 Neo4j 图转储为 Cypher 并从 Cypher 重新加载它?

    每个熟悉 MySQL 的人都可能使用过 mysqldump 命令 它可以生成代表 MySQL 数据库中的架构和数据的 SQL 语句文件 这些 SQL 文本文件通常用于多种用途 备份 播种副本 在安装之间复制数据库 将产品数据库复制到临时环境
  • 防止重复数据输入mysql数据库

    我试图让我的电子邮件订阅服务拒绝数据库中已存在的电子邮件 这样用户就不会订阅同一封电子邮件两次 这就是我所拥有的 但它不起作用 有什么想法吗
  • MySQL LAST_INSERT_ID() 和 FOUND_ROWS()

    当 PHP 脚本每秒有数百个查询时会发生什么 它会影响这些函数吗 是否保证它们会返回当前脚本中最后一个插入语句中最后插入的 id 它会返回当前脚本中最后一次选择的行数吗 如果同时从另一个脚本进行新的插入或选择 在 FOUND ROWS 的情
  • Delphi XE5 FireDAC 错误:无法加载供应商库 [libmysql.dll 或 libmysqld.dll]

    我在 Windows 7 64 位上使用 Delphi XE5 只是尝试 FireDAC 组件 我正在使用一个 TFDConnection 组件连接到本地 MySQL 数据库 v5 6 15 我已经将 libmysql dll 32位 v5
  • MyBatis 枚举的使用

    我知道以前有人问过这个问题 但我无法根据迄今为止找到的信息实施解决方案 所以也许有人可以向我解释一下 我有一个表 状态 它有两列 id 和 name id是PK 我不想使用 POJO Status 而是使用枚举 我创建了这样一个枚举 如下所
  • 日常 MySQL(部分和过滤)复制的最佳实践?

    我有一个相当大的数据库 有超过 40 个表 我只需要复制几个表 5 并且每个表也被过滤 我正在寻找一些复制这些数据的最佳实践 每天就足够了 我可以只选择几个表并为每个表包含一些 WHERE 子句 我正在考虑为每个表启动 mysqldump
  • 通过 PDO 将双精度数插入 MySQL 时精度损失

    我遇到了这种非常烦人的行为 我想知道我是否做错了什么 或者这是否是故意的 如果是的话 为什么 每当我在 php 5 3 中有一个 double 类型的变量 并且想将其插入到数据库 MYSQL 5 0 的 double 类型字段中时 该值总是
  • 将我的 Laravel 连接到外部数据库

    如何将 Laravel 连接到外部数据库 示例 我的本地计算机上有一个 Laravel 它在 xampp 上运行 我希望它连接到云服务器数据库 打开 env文件并编辑它 只需设置正确的外部数据库凭据 DB CONNECTION mysql
  • SQL 查询结果为字符串(或变量)

    是否可以将SQL查询结果输出到一个字符串或变量中 我的php和mysql不好 假设我有数据库 agents 其中包含列 agent id agent fname agent lname agent dept 使用此查询 sql SELECT
  • SQL Server 标识列值从 0 而不是 1 开始

    我遇到了一个奇怪的情况 数据库中的某些表的 ID 从 0 开始 即使 TABLE CREATE 的 IDENTITY 1 1 也是如此 对于某些表来说是这样 但对于其他表则不然 它一直有效到今天 我尝试过重置身份列 DBCC CHECKID
  • Yii2:无法将列值更新+1

    创建新记录时 我需要将列值更新 1 public function actionCreate model new CreateBookings if model gt load Yii app gt request gt post Yii
  • 如何获取所有mysql元组结果并转换为json

    我能够从表中获取单个数据 但是当我试图获取表上的所有数据时 我只得到一行 cnn execute sql rows cnn fetchall column t 0 for t in cnn description for row in ro

随机推荐