MySQL AUTO_INCREMENT 原理解析

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 在关系型数据库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的偏移值会是建表以来生成过的最大值;
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
19天前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
52 1
|
1天前
|
存储 缓存 算法
HashMap深度解析:从原理到实战
HashMap,作为Java集合框架中的一个核心组件,以其高效的键值对存储和检索机制,在软件开发中扮演着举足轻重的角色。作为一名资深的AI工程师,深入理解HashMap的原理、历史、业务场景以及实战应用,对于提升数据处理和算法实现的效率至关重要。本文将通过手绘结构图、流程图,结合Java代码示例,全方位解析HashMap,帮助读者从理论到实践全面掌握这一关键技术。
28 13
|
3天前
|
存储 关系型数据库 MySQL
double ,FLOAT还是double(m,n)--深入解析MySQL数据库中双精度浮点数的使用
本文探讨了在MySQL中使用`float`和`double`时指定精度和刻度的影响。对于`float`,指定精度会影响存储大小:0-23位使用4字节单精度存储,24-53位使用8字节双精度存储。而对于`double`,指定精度和刻度对存储空间没有影响,但可以限制数值的输入范围,提高数据的规范性和业务意义。从性能角度看,`float`和`double`的区别不大,但在存储空间和数据输入方面,指定精度和刻度有助于优化和约束。
|
3天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
23 5
|
1天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
25 9
|
2天前
|
存储 SQL 关系型数据库
MySQL进阶突击系列(03) MySQL架构原理solo九魂17环连问 | 给大厂面试官的一封信
本文介绍了MySQL架构原理、存储引擎和索引的相关知识点,涵盖查询和更新SQL的执行过程、MySQL各组件的作用、存储引擎的类型及特性、索引的建立和使用原则,以及二叉树、平衡二叉树和B树的区别。通过这些内容,帮助读者深入了解MySQL的工作机制,提高数据库管理和优化能力。
|
15天前
|
SQL 存储 关系型数据库
MySQL进阶突击系列(01)一条简单SQL搞懂MySQL架构原理 | 含实用命令参数集
本文从MySQL的架构原理出发,详细介绍其SQL查询的全过程,涵盖客户端发起SQL查询、服务端SQL接口、解析器、优化器、存储引擎及日志数据等内容。同时提供了MySQL常用的管理命令参数集,帮助读者深入了解MySQL的技术细节和优化方法。
|
27天前
|
运维 持续交付 虚拟化
深入解析Docker容器化技术的核心原理
深入解析Docker容器化技术的核心原理
45 1
|
1月前
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
105 3
|
20天前
|
存储 供应链 算法
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景
44 0

推荐镜像

更多