AUTO_INCREMENT 是 MySQL 最常用的自增主鍵機制,但不同儲存引擎(MyISAM、InnoDB、Memory、BDB 等)行為差異巨大。本文系統梳理用法細節、引擎差異表、進階技巧與生產環境避坑指南。
CREATE TABLE `test` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(15) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4;
AUTO_INCREMENT=100:指定起始值(僅 MyISAM、Memory、InnoDB 8.0+ 支援)。NOT NULL、PRIMARY KEY 或 UNIQUE KEY 的第一列。NULL、0 或省略該欄位 → 自動生成下一個序列值。值 + 1(可跳號)。LAST_INSERT_ID() 返回當前會話最後生成的自增值,安全於併發環境。REPLACE / INSERT ... ON DUPLICATE KEY UPDATE 觸發自增值消耗(即使未實際插入新行),導致「自增 ID 跳號」。| 特性 | MyISAM | InnoDB | Memory (HEAP) | BDB |
|---|---|---|---|---|
| 最大值刪除後是否重用 | 是 | 否 (8.0 前) | 否 | 是 |
支援 AUTO_INCREMENT=n 建表/ALTER | 是 | 8.0+ 支援 | 是 | 否 |
| 支援複合索引多序列 | 是 | 否 | 否 | 是 |
| 事務回滾是否消耗自增值 | N/A (無事務) | 是 (間隙鎖機制) | N/A | N/A |
| 持久化計數器存儲 | .MYI 文件 | 內存 (8.0 持久化到 redo log) | 僅內存 | .db 文件 |
innodb_autoinc_lock_mode (0/1/2) 控制鎖粒度,影響併發插入效能與語句型複刻安全性。生產建議設為 2 (interleaved),配合 Row 格式 Binlog。MAX_ID + 1,避免主鍵衝突與外鍵引用混亂。-- 專用序列表
CREATE TABLE `id_generator` (`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
-- 使用時
INSERT INTO `id_generator` VALUES (NULL);
SET @new_id = LAST_INSERT_ID();
INSERT INTO `main_table` (`id`, `data`) VALUES (@new_id, '...');
ALTER TABLE `tbl` AUTO_INCREMENT = 1000; -- 僅增大,不可縮小至現有最大值以下
-- 或截斷表(重置為 1,慎用!)
TRUNCATE TABLE `tbl`;
-- 錯誤:DELETE FROM tbl; -- 觸發優化,實際 TRUNCATE,自增歸 1
-- 正確:DELETE FROM tbl WHERE 1; -- 逐行刪除,保留自增計數器
-- 或:TRUNCATE TABLE tbl; -- 明確意圖重置
使用 innodb_autoinc_lock_mode=2 時,單條 INSERT ... VALUES (...), (...), ... 可一次性分配連續 ID 範圍,減少鎖爭用。避免在循環中單條執行 INSERT。
SELECT TABLE_NAME, AUTO_INCREMENT,
CASE DATA_TYPE
WHEN 'tinyint' THEN 255
WHEN 'smallint' THEN 65535
WHEN 'mediumint' THEN 16777215
WHEN 'int' THEN 4294967295
WHEN 'bigint' THEN 18446744073709551615
END AS MAX_VAL
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_db' AND AUTO_INCREMENT IS NOT NULL;
建議主鍵使用 BIGINT UNSIGNED,單表數量極大時考慮分庫分表或 UUID/Snowflake ID。
理解引擎差異、鎖模式、持久化機制,合理選擇類型(優先 BIGINT UNSIGNED),監控耗盡風險,避免全表刪除、事務回滾導致的跳號驚訝,即可駕馭 AUTO_INCREMENT。