在 MySQL 中,AUTO_INCREMENT
(自增主键)的行为与存储引擎有很大关系,主要体现在 MyISAM 和 InnoDB 两种存储引擎在存储自增 ID 以及如何管理自增主键最大 ID 的方式上。
1. MyISAM 存储引擎
- 自增 ID 存储方式:
- 在 MyISAM 存储引擎中,自增 ID 的值通常保存在
.frm
文件(表结构文件)和 .MYI
文件(索引文件)中。
- MyISAM 使用一个单独的 自增计数器 来管理自增列的值。这个计数器的值存储在 MYI 文件的一个内存中,并且每次插入新记录时都会增加。
- 如何存储最大 ID:
- MyISAM 存储引擎的自增 ID 的最大值是通过维护一个 内部计数器 来实现的。
- 当你查询表的
AUTO_INCREMENT
列时,MyISAM 会从该计数器中获取下一个值,并且它会记住最后分配的最大 ID。
- 计数器的更新:每次插入时,计数器会递增,并在每次操作时直接更新,因此如果在插入期间出现崩溃,MyISAM 可能会丢失该计数器的信息,这可能导致 ID 的间隙(例如,如果服务器崩溃,下一次插入的 ID 可能会大于之前的最大值)。
- 并发控制:
- MyISAM 在处理
AUTO_INCREMENT
值时没有行级锁,仅使用表级锁,因此可能在高并发环境下遇到性能瓶颈。
2. InnoDB 存储引擎
-
自增 ID 存储方式:
- InnoDB 存储引擎的自增 ID 存储与 MyISAM 相比略有不同,尤其是在事务支持和一致性上。InnoDB 使用一种全局的 自增计数器 来保证自增 ID 的生成。
- 该计数器存储在 InnoDB 的 内部系统表 中(
information_schema
中的 innodb_status
和 mysql.innodb_table_stats
)。在多事务的环境下,InnoDB 会通过此全局计数器来保证不同事务间的自增值不会冲突。
-
如何存储最大 ID:
- InnoDB 使用一个特殊的机制来管理最大
AUTO_INCREMENT
值,称为 自增缓存。每个 InnoDB 表都维护一个 自增游标,该游标保存在一个内部的内存中。
- 计数器的更新:InnoDB 会在插入数据时根据 自增缓存 分配自增值,这样可以减少访问磁盘的次数。每次使用一个自增值时,都会更新该游标,以确保生成的自增 ID 是递增的。
- 持久化存储:InnoDB 会将自增的最大值保存在 表的元数据 中,即使数据库崩溃或重启,系统会从持久化存储中恢复自增值,避免了 ID 重复或丢失的情况。
-
并发控制:
- InnoDB 在自增 ID 的分配上使用了 行级锁 和 事务隔离,即使在高并发场景下,也能够保证多个事务之间自增 ID 的唯一性和顺序性。
- 如果表是 InnoDB 的事务表,它将使用锁机制来防止并发写入同一 ID,确保自增 ID 是唯一的。