关于 MySQL insert 和自增 ID 的奇怪事件

简介: 关于 MySQL insert 和自增 ID 的奇怪事件

你好,我是yes。

上周五,我的读者向我提了个问题,这个问题既熟悉又生僻,还是挺有意思的,所以我在这里分享一下。

首先有建立一张表

CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

表没什么花头,主键是 ID,然后是自增的。

此时执行一条插入语句:

insert into t (id,c,d) values (1,1,1),(null,2,2),(7,7,7),(null,4,4);

语句中既有指定的 ID,又有让 MySQL 自己计算的自增 ID。

然后此时,再执行一条sql

insert into t (id,c,d) values (null,9,9);

你觉得这条插入的 ID 应该是几?

你肯定以为是 9 ,实际上这条新纪录的 ID 是 10。

乍一看,不对啊,第一条插入语句的最后一个记录是 (null,4,4),它的 ID 是 8 ,那为什么紧接着的后面一个插入自增 ID 直接变到了 10 而不是 9 ?

为什么中间空了一个 ID?

讲实话,我也不知道,于是我去官网寻寻觅觅,果然皇天不负有心人,嘻嘻。


image.png


这种一条语句里面,即包含指定 ID 又有自增 ID 的叫做Mixed-mode inserts

然后关于自增 ID 的模式,又分为三种,我在之前的文章分析过:


image.png


image.png


简单的来了个机翻:

例外情况是“混合模式插入”,其中用户为多行“简单插入”中的某些(但不是全部)行提供 AUTO_INCREMENT 列的显式值。 对于此类插入,InnoDB 分配的自动增量值多于要插入的行数。 但是,所有自动分配的值都是连续生成的(因此高于)由最近执行的前一条语句生成的自动增量值。 “多余”的数字丢失

好了,破案了,官网上已经写的很清楚了,这样的插入在innodb_autoinc_lock_mode = 1的情况下,InnoDB 就是会分配多余插入行数的 ID 数,而多出来的 ID 就被丢弃了。

所以后面的插入看起来就和前面断掉了,搞得像一部分 ID 莫名其妙被吃了一样。

那为什么会 InnoDB 要这样实现呢?

如果想具体知道这个问题,那肯定得看源码了,那成本就太大了。

我盲猜猜,你一条插入里面即自己设定了 ID,又让 InnoDB 计算自增 ID,在代码实现上估计有点难度,想要做到完美的自增 ID 序列估计成本有点大。

简单来说就是得不偿失,自增  ID 这么多,少一两个不要紧,所以就简单实现,一次多准备点,这样插入就不会出错啦~


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
5月前
|
SQL 人工智能 关系型数据库
如何使用MySQL的事件调度器?
MySQL事件调度器允许在指定时间或间隔自动执行SQL语句,可用于数据清理、报告生成等任务。本文介绍其配置、创建、修改、删除事件的方法,并提供Java操作示例代码,帮助实现数据库定时任务管理。
223 0
|
NoSQL 关系型数据库 MySQL
2024Mysql And Redis基础与进阶操作系列(4-2)作者——LJS[含MySQL非空、唯一性、PRIMARY KEY、自增列/自增约束举例说明等详解步骤及常见报错问题对应的解决方法]
24MySQL非空、唯一性、PRIMARY KEY、自增列/自增约束举例说明等详解步骤及常见报错问题对应的解决方法(4-2) 学不会你来砍我!!!
|
9月前
|
人工智能 关系型数据库 MySQL
解决MySQL自增id用尽的问题
本文介绍了解决文章点击记录表(`article_click_record`)数据量激增问题的方案。由于用户量大,每天新增约400万条记录,导致表id接近溢出(2,100,000,000),且占用空间超320G。解决方案包括:1) 新建`article_click_record_new`表,将id类型改为BIGINT以避免溢出;2) 过渡阶段同时写入新旧表,待旧表id溢出后切换至新表;3) 定时清理过期数据或转移旧表内容。实现方式涉及修改相关接口和服务逻辑,确保业务平稳过渡。
201 5
|
关系型数据库 MySQL
MySQL自增ID用完会怎样?
MySQL自增ID用完会怎样?
|
12月前
|
存储 关系型数据库 MySQL
MySQL主键谁与争锋:MySQL为何钟爱自增主键ID+UUID?
本文深入探讨了在MySQL中使用自增类型主键的优势与局限性。自增主键通过保证数据的有序性和减少索引维护成本,提升了查询和插入性能,简化了数据库管理和维护,并提高了数据一致性。然而,在某些业务场景下,如跨表唯一性需求或分布式系统中,自增主键可能无法满足要求,且存在主键值易预测的安全风险。因此,选择主键类型时需综合考虑业务需求和应用场景。
417 2
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
591 3
|
存储 关系型数据库 MySQL
MySQL 8.0特性-自增变量的持久化
【11月更文挑战第8天】在 MySQL 8.0 之前,自增变量(`AUTO_INCREMENT`)的行为在服务器重启后可能会发生变化,导致意外结果。MySQL 8.0 引入了自增变量的持久化特性,将其信息存储在数据字典中,确保重启后的一致性。这提高了开发和管理的稳定性,减少了主键冲突和数据不一致的风险。默认情况下,MySQL 8.0 启用了这一特性,但在升级时需注意行为变化。
275 1
|
存储 监控 关系型数据库
MySQL自增ID耗尽解决方案:应对策略与实践技巧
在MySQL数据库中,自增ID(AUTO_INCREMENT)是一种特殊的属性,用于自动为新插入的行生成唯一的标识符。然而,当自增ID达到其最大值时,会发生什么?又该如何解决?本文将探讨MySQL自增ID耗尽的问题,并提供一些实用的解决方案。
486 1
|
SQL 关系型数据库 MySQL
MySQL设置表自增步长
MySQL设置表自增步长
573 0
|
3月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
161 3