MySQL AUTO_INCREMENT 原理解析

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: 在关系型数据库MySQL中,AUTO_INCREMENT是数据库的一个属性,该属性使得在申明了AUTO_INCREMENT的列中可以自动生成唯一的递增值。本文详细介绍了在InnoDB及MyISAM引擎中AUTO_INCREMENT的使用原理及一些容易被忽略的问题。

一、引言

在关系型数据库MySQL中,AUTO_INCREMENT是数据库的一个属性,该属性使得在申明了AUTO_INCREMENT的列中可以自动生成唯一的递增值。

二、AUTO_INCREMENT使用示例

InnoDB引擎条件下使用示列:

通常情况,我们在定义数据表中为整数类型主键列时,应用AUTO_INCREMENT 属性,用以保证INSERT的所有记录都具有一个唯一的id,建表示列如下:

CREATE TABLE students (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name VARCHAR(10) NOT NULL,
     PRIMARY KEY (id)
)ENGINE=INNODB;

在建表成功后,我们执行如下SQL语句,由最终的查询结果可以看出在未申明主键id值时,AUTO_INCREMENT为我们自动生成了递增的主键id,并且默认偏移值从1开始递增。当然我们也可以在建表时主动申明初始偏移值从多少开始。

INSERT INTO students (name) VALUES
    ('Ross'),('Julie'),('Gloria'),('Carol');
SELECT * FROM students;
id  name
1 Ross
2 Julie
3 Gloria
4 Carol

此时我们再执行包含主动申明主键id值的如下语句:

INSERT INTO students (id,name) VALUES(0,'Joan'),(NULL,'Niki'),(20,'Betty');
INSERT INTO students (name) VALUES('Linda');
SELECT * FROM students;
id  name
1 Ross
2 Julie
3 Gloria
4 Carol
5 Joan
6 Niki
20 Betty
21 Linda

由上述执行语句及查询结果可以看出:

  1. 当我们申明新增记录主键id小于当前AUTO_INCREMENT根据偏移值应该自动生成的值时,则在写入数据时主动申明的id值也无效,数据库中最终写入的值依然是AUTO_INCREMENT生成的值;
  2. 当我们申明新增记录主键id为NULL时,数据库中最终写入的值将是AUTO_INCREMENT生成的值;
  3. 当我们申明新增记录主键id大于本次写入AUTO_INCREMENT根据偏移值应该主动生成的值时,则数据库中最终写入的值为我们主动申明的值,并且后续AUTO_INCREMENT将以此申明的值为偏移值进行递增生成;

现在我们删除一条记录并再写入一条记录看看数据库是如何表现,从下面的执行结果可以得出在执行DELETE语句时并不会影响AUTO_INCREMENT已记录的偏移值。

DELETE from students where name='Linda';
INSERT INTO students (name) VALUES('Linda');
SELECT * FROM students;
id  name
1 Ross
2 Julie
3 Gloria
4 Carol
5 Joan
6 Niki
20 Betty
22 Linda

注意:

  • 在MySQL8.0版本以前当我们执行了上述DELETE语句重启数据库再写入一条记录时,此时id的值为21,而MySQL8.0及以后的版本相同操作的情况下id生成的值为22。因为在8.0以前的版本AUTO_INCREMENT的值保存在内存中,重启数据库后将偏移量初始化为当前表中的实际最大记录值,而8.0以后的版本AUTO_INCREMENT的值做了持久化,因此重启后偏移量依然为建表以来生成的过的最大值。
  • InnoDB引擎中申明为AUTO_INCREMENT的列必须为索引列,否则建表时会报“1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for XXX”错误,并且在组合索引时申明为AUTO_INCREMENT的列为组合索引的第一列,否则会报“1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key”错误。

MyISAM引擎条件下使用示列

MyISAM引擎中申明为AUTO_INCREMENT属性的字段必须是索引字段,但与InnoDB引擎不同的是:在组合索引的情况下,申明为AUTO_INCREMENT的字段不要求为组合索引的第一列

CREATE TABLE countries_test1 (
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    continent CHAR(20) NOT NULL,
    country_name CHAR(30) NOT NULL,
    PRIMARY KEY (id,continent)
) ENGINE=MyISAM;
INSERT INTO countries_test1 (continent,country_name) VALUES
    ('Asia','中国'),('Asia','日本'),
    ('North America','美国'),('Asia','韩国'),('Europe','英国'),
    ('Europe','德国');
INSERT INTO countries_test1 (id,continent,country_name) VALUE (0,'Asia','越南'),(NULL,'Asia','泰国'),(10,'Asia','新加坡');
INSERT INTO countries_test1 (continent,country_name) VALUE ('Asia','老挝');
DELETE from countries_test1 where country_name='老挝';
INSERT INTO countries_test1 (continent,country_name) VALUE ('Asia','老挝');
SELECT * FROM countries_test1;
id  continent country_name
1 Asia  中国
2 Asia  日本
3 North America 美国
4 Asia  韩国
5 Europe  英国
6 Europe  德国
7 Asia  越南
8 Asia  泰国
10 Asia 新加坡
12 Asia 老挝

从上面的执行示列可以看出,在MyISAM引擎中,当申明为AUTO_INCREMENT字段的索引中,如果AUTO_INCREMENT字段在索引的第一列则执行效果和InnoDB引擎中效果一样,接下来我们将组合索引中申明为AUTO_INCREMENT的列不为第一列并查看实际执行效果。

CREATE TABLE countries_test2 (
    continent CHAR(20) NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    country_name CHAR(30) NOT NULL,
    PRIMARY KEY (continent,id)   -- 注意这里组合索引字段申明顺序
) ENGINE=MyISAM;
INSERT INTO countries_test2 (continent,country_name) VALUES
    ('Asia','中国'),('Asia','日本'),
    ('North America','美国'),('Asia','韩国'),('Europe','英国'),
    ('Europe','德国');
SELECT * FROM countries_test2 ORDER BY continent,ID;
continent id  country_name
Asia  1  中国
Asia  2  日本
Asia  3  韩国
Europe  1  英国
Europe  2  德国
North America 1 美国

从上面的实验结果可以看出,在组合索引中申明为AUTO_INCREMENT列不为第一列时,只有当索引中第一列的值相同时,相同组内的AUTO_INCREMENT值才会自增,这种特性是的在将数据放入有序组的场景中特别有用。接下来在同一数据组内同样测试主动申明AUTO_INCREMENT建的值相关结果如下示例所示,从实际结果可看出同组内的自增表现与InnoDB引擎中一致。

INSERT INTO countries_test2 (id,continent,country_name) VALUE (0,'Asia','越南'),(NULL,'Asia','泰国'),(10,'Asia','新加坡');
INSERT INTO countries_test2 (continent,country_name) VALUE ('Asia','老挝');
SELECT * FROM countries_test2 ORDER BY continent,ID;
continent id  country_name
Asia  1  中国
Asia  2  日本
Asia  3  韩国
Asia  4  越南
Asia  5  泰国
Asia  10  新加坡
Asia  11  老挝
Europe  1  英国
Europe  2  德国
North America 1 美国

特别需要注意的是:在这中表结构设计中,我们删除一条同组中的自增id最大的一条记录,自增id的偏移量也会随之减小,当再插入一条记录时,自增id所取的偏移量为当前同组中Max(id)++后的值。相关示例如下所示:

DELETE from countries_test2 where country_name='老挝';
INSERT INTO countries_test2 (continent,country_name) VALUE ('Asia','老挝2');
SELECT * FROM countries_test2 ORDER BY continent,ID;
continent id  country_name
Asia  1  中国
Asia  2  日本
Asia  3  韩国
Asia  4  越南
Asia  5  泰国
Asia  10  新加坡
Asia  11  老挝2
Europe  1  英国
Europe  2  德国
North America 1 美国

三、AUTO_INCREMENT使用总结

  1. InnoDB和MyISAM引擎中申明为AUTO_INCREMENT的列均需为索引列,在参与组合索引定义时InnoDB中需要为组合索引第一列,而MyISAM中可以不为第一列;
  2. AUTO_INCREMENT默认偏移量从1开始,也可以在建表时自定义初始偏移量;
  3. 当向带有 AUTO_INCREMENT 的列插入 NULL 值时,MySQL 会忽略 NULL 值并自动生成一个自增值;
  4. 当写入数据时主动写入AUTO_INCREMENT的列的值,如果待写入的值大于AUTO_INCREMENT即将生成的偏移量的值则使用主动写入的值,否则MySQL 会忽略主动写入值并自动生成一个自增值;
  5. 使用 DELETE 或 TRUNCATE TABLE 语句删除表中的数据行不会重置 AUTO_INCREMENT的偏移值;
  6. MyISAM引擎中当AUTO_INCREMENT列为索引第一列时使用方式和InnoDB一样,但不为第一列时相同组内的AUTO_INCREMENT值才会自增;
  7. MySQL8.0版本以前版本AUTO_INCREMENT存在内存中,因此重启数据库AUTO_INCREMENT的偏移值会初始化为当前表中的最大值,而8.0及以后的版本AUTO_INCREMENT做了持久化,重启数据库AUTO_INCREMENT的偏移值会是建表以来生成过的最大值;
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
9月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
自然语言处理 搜索推荐 关系型数据库
MySQL实现文档全文搜索,分词匹配多段落重排展示,知识库搜索原理分享
本文介绍了在文档管理系统中实现高效全文搜索的方案。为解决原有ES搜索引擎私有化部署复杂、运维成本高的问题,我们转而使用MySQL实现搜索功能。通过对用户输入预处理、数据库模糊匹配、结果分段与关键字标红等步骤,实现了精准且高效的搜索效果。目前方案适用于中小企业,未来将根据需求优化并可能重新引入专业搜索引擎以提升性能。
626 5
|
安全 算法 网络协议
解析:HTTPS通过SSL/TLS证书加密的原理与逻辑
HTTPS通过SSL/TLS证书加密,结合对称与非对称加密及数字证书验证实现安全通信。首先,服务器发送含公钥的数字证书,客户端验证其合法性后生成随机数并用公钥加密发送给服务器,双方据此生成相同的对称密钥。后续通信使用对称加密确保高效性和安全性。同时,数字证书验证服务器身份,防止中间人攻击;哈希算法和数字签名确保数据完整性,防止篡改。整个流程保障了身份认证、数据加密和完整性保护。
|
8月前
|
存储 SQL 关系型数据库
MySQL中binlog、redolog与undolog的不同之处解析
每个都扮演回答回溯与错误修正机构角色: BinLog像历史记载员详细记载每件大大小小事件; RedoLog则像紧急救援队伍遇见突發情況追踪最后活动轨迹尽力补救; UndoLog就类似时间机器可倒带历史让一切归位原始样貌同时兼具平行宇宙观察能让多人同时看见各自期望看见历程而互不干扰.
491 9
|
9月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
234 2
|
9月前
|
SQL 关系型数据库 MySQL
MySQL group by 底层原理详解。group by 执行 慢 原因深度分析。(图解+秒懂+史上最全)
MySQL group by 底层原理详解。group by 执行 慢 原因深度分析。(图解+秒懂+史上最全)
MySQL group by 底层原理详解。group by 执行 慢 原因深度分析。(图解+秒懂+史上最全)
|
9月前
|
存储 SQL 关系型数据库
MySQL 核心知识与性能优化全解析
我整理的这份内容涵盖了 MySQL 诸多核心知识。包括查询语句的书写与执行顺序,多表查询的连接方式及内、外连接的区别。还讲了 CHAR 和 VARCHAR 的差异,索引的类型、底层结构、聚簇与非聚簇之分,以及回表查询、覆盖索引、左前缀原则和索引失效情形,还有建索引的取舍。对比了 MyISAM 和 InnoDB 存储引擎的不同,提及性能优化的多方面方法,以及超大分页处理、慢查询定位与分析等,最后提到了锁和分库分表可参考相关资料。
201 0
|
机器学习/深度学习 数据可视化 PyTorch
深入解析图神经网络注意力机制:数学原理与可视化实现
本文深入解析了图神经网络(GNNs)中自注意力机制的内部运作原理,通过可视化和数学推导揭示其工作机制。文章采用“位置-转移图”概念框架,并使用NumPy实现代码示例,逐步拆解自注意力层的计算过程。文中详细展示了从节点特征矩阵、邻接矩阵到生成注意力权重的具体步骤,并通过四个类(GAL1至GAL4)模拟了整个计算流程。最终,结合实际PyTorch Geometric库中的代码,对比分析了核心逻辑,为理解GNN自注意力机制提供了清晰的学习路径。
851 7
深入解析图神经网络注意力机制:数学原理与可视化实现
|
机器学习/深度学习 缓存 自然语言处理
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
1535 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
|
10月前
|
关系型数据库 MySQL
MySQL字符串拼接方法全解析
本文介绍了四种常用的字符串处理函数及其用法。方法一:CONCAT,用于基础拼接,参数含NULL时返回NULL;方法二:CONCAT_WS,带分隔符拼接,自动忽略NULL值;方法三:GROUP_CONCAT,适用于分组拼接,支持去重、排序和自定义分隔符;方法四:算术运算符拼接,仅适用于数值类型,字符串会尝试转为数值处理。通过示例展示了各函数的特点与应用场景。

推荐镜像

更多