首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | 基础架构:一条SQL查询语句是如何执行的?
02 | 日志系统:一条SQL更新语句是如何执行的?
03 | 事务隔离:为什么你改了我还看不见?
04 | 深入浅出索引(上)
05 | 深入浅出索引(下)
06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?
07 | 行锁功过:怎么减少行锁对性能的影响?
08 | 事务到底是隔离的还是不隔离的?
09 | 普通索引和唯一索引,应该怎么选择?
10 | MySQL为什么有时候会选错索引?
11 | 怎么给字符串字段加索引?
12 | 为什么我的MySQL会“抖”一下?
13 | 为什么表数据删掉一半,表文件大小不变?
14 | count(*)这么慢,我该怎么办?
15 | 答疑文章(一):日志和索引相关问题
16 | “order by”是怎么工作的?
17 | 如何正确地显示随机消息?
18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?
19 | 为什么我只查一行的语句,也执行这么慢?
20 | 幻读是什么,幻读有什么问题?
21 | 为什么我只改一行的语句,锁这么多?
22 | MySQL有哪些“饮鸩止渴”提高性能的方法?
23 | MySQL是怎么保证数据不丢的?
24 | MySQL是怎么保证主备一致的?
25 | MySQL是怎么保证高可用的?
26 | 备库为什么会延迟好几个小时?
27 | 主库出问题了,从库怎么办?
28 | 读写分离有哪些坑?
29 | 如何判断一个数据库是不是出问题了?
30 | 答疑文章(二):用动态的观点看加锁
31 | 误删数据后除了跑路,还能怎么办?
32 | 为什么还有kill不掉的语句?
33 | 我查这么多数据,会不会把数据库内存打爆?
34 | 到底可不可以使用join?
35 | join语句怎么优化?
36 | 为什么临时表可以重名?
37 | 什么时候会使用内部临时表?
38 | 都说InnoDB好,那还要不要使用Memory引擎?
39 | 自增主键为什么不是连续的?
40 | insert语句的锁为什么这么多?
41 | 怎么最快地复制一张表?
42 | grant之后要跟着flush privileges吗?
43 | 要不要使用分区表?
44 | 答疑文章(三):说一说这些好问题
45 | 自增id用完怎么办?
当前位置:
首页>>
技术小册>>
MySQL 实战 45 讲
小册名称:MySQL 实战 45 讲
### 39 | 自增主键为什么不是连续的? 在数据库设计和应用开发中,自增主键(Auto-Increment Primary Key)作为一种常见的数据库主键生成策略,被广泛用于MySQL等关系型数据库系统中。自增主键的主要优点是简单、高效,并且能够在一定程度上保证数据的唯一性和有序性。然而,很多开发者在使用过程中会发现,尽管设置了自增主键,但在实际插入数据时,主键值并不总是连续的,这常常引发困惑。本章节将深入探讨自增主键不连续的原因,并解析其背后的机制与逻辑。 #### 一、自增主键的基本原理 首先,我们需要理解自增主键的基本原理。在MySQL中,当表被定义为使用自增主键时,每当向表中插入新记录而不显式指定主键值时,数据库系统会自动为新记录生成一个唯一的、比当前最大值大1的主键值。这个机制通过内部维护一个计数器(或称为“自增值”)来实现,每次插入新记录时,该计数器就会递增。 #### 二、自增主键不连续的主要原因 尽管自增主键的设计初衷是生成连续的整数序列,但在实际应用中,由于多种原因,主键值并不总是连续的。以下是一些常见的原因: ##### 1. **事务回滚** 在事务性数据库系统中,如果包含自增主键插入操作的事务被回滚,那么该操作生成的自增值将会被系统保留,不会被重新使用。这意味着,尽管该次插入尝试被撤销,但自增值已经增加,导致后续的自增主键值出现不连续。 **示例**:假设当前自增值为10,事务A尝试插入一条记录并生成主键11,但由于某种原因事务A被回滚。此时,尽管记录未成功插入,但自增值已增加到11,下一个插入操作将生成主键12,造成不连续。 ##### 2. **批量插入与删除** 当执行批量插入操作后,再对部分或全部记录进行删除时,被删除的记录占用的自增值不会被回收重用。这些空出的自增值将永远保持空闲状态,除非表被重建或清空。 **示例**:批量插入10条记录,自增值从10递增到19。随后,删除这10条记录中的5条,自增值已到达19,但即便删除操作后,自增主键的下一个值仍然是20,不会回退到之前的空值。 ##### 3. **复制和分区表** 在MySQL的复制架构或分区表中,自增值的管理可能更加复杂。尤其是在主从复制环境中,如果设置了自增值的偏移量或在不同节点上独立管理自增值,那么不同节点上生成的自增值可能不连续,甚至在合并数据时出现冲突。 **示例**:在双主复制环境中,每个主节点可能独立维护自增值,导致两个节点上的自增值不连续。当数据同步时,需要特别注意避免主键冲突。 ##### 4. **显式指定主键值** 虽然设置了自增主键,但开发者仍然可以在插入记录时显式指定主键值。如果指定的值大于当前自增值,系统将会更新自增值为该指定值(或更大值,取决于MySQL的具体版本和配置)。这也会导致自增值跳跃,造成不连续。 **示例**:当前自增值为10,插入新记录时显式指定主键为15,则下一条记录的自增值将从16开始。 ##### 5. **系统重启与崩溃** 在某些情况下,数据库服务器的重启或崩溃也可能影响自增值的连续性。虽然现代数据库系统都有完善的恢复机制,但在极端情况下,自增值的连续性可能仍然会受到影响。 #### 三、如何处理自增主键不连续的问题 自增主键不连续本身并不一定是问题,它更多是一种现象或结果。然而,在某些特定场景下,如需要保持主键值的连续性以满足特定业务逻辑或性能优化需求时,就需要采取一些措施来应对。 ##### 1. **接受不连续** 在大多数情况下,自增主键的不连续性对数据库性能和功能没有实质性影响。因此,最简单也是最常见的处理方式是接受这种不连续性,将其作为数据库正常运作的一部分。 ##### 2. **重新设计主键策略** 如果业务逻辑确实需要连续的主键值,可以考虑重新设计主键生成策略。例如,使用UUID作为主键(尽管这会影响性能),或者开发自定义的主键生成服务,如基于时间戳和序列号的组合。 ##### 3. **定期重置自增值** 在某些情况下,如果可以接受数据迁移或重建表的代价,可以通过重置自增值来恢复连续性。但这通常不推荐作为常规操作,因为它可能引入其他问题,如主键冲突和数据一致性风险等。 ##### 4. **使用触发器或存储过程** 通过编写触发器或存储过程来管理自增值的分配,可以在一定程度上控制主键的连续性。但这种方法增加了数据库的复杂性和维护成本,需要谨慎使用。 #### 四、总结 自增主键不连续是MySQL等关系型数据库在使用自增主键时常见的现象,它主要由事务回滚、批量插入与删除、复制和分区表、显式指定主键值以及系统重启与崩溃等多种因素造成。虽然不连续性本身并不一定是问题,但在某些特定场景下可能需要采取措施来应对。理解自增主键不连续的原因和机制,有助于开发者更好地设计数据库和应用系统,避免潜在的问题和陷阱。
上一篇:
38 | 都说InnoDB好,那还要不要使用Memory引擎?
下一篇:
40 | insert语句的锁为什么这么多?
该分类下的相关小册推荐:
MySQL从入门到精通(二)
MySQL8.0入门与实践
细说MySQL(零基础到高级应用)
MySQL从入门到精通(五)
MySQL从入门到精通(四)
MySQL从入门到精通(三)
SQL零基础到熟练应用(增删改查)
MySQL必会核心问题
MySQL从入门到精通(一)