AUTO_INCREMENT 是 MySQL 最常用卻最易被忽視的特性。不同儲存引擎(MyISAM、InnoDB、MEMORY、BDB、Archive)行為差異巨大,配合 LAST_INSERT_ID()、複合索引、重置策略等進階用法,能解決分散式 ID、熱點爭用、審計追蹤等棘手問題。本文系統梳理全引擎行為差異、核心限制、進階技巧與生產級避坑指南。
CREATE TABLE `t_auto` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100; -- 指定起始值
黃金法則:UNSIGNED(翻倍容量)+ NOT NULL + PRIMARY KEY / UNIQUE KEY。
| 特性 | MyISAM | InnoDB | MEMORY | BDB | Archive |
|---|---|---|---|---|---|
| 刪除最大值後重用 | 是 | 否 | 否 | 是 | 否 |
| 建表指定起始值 | AUTO_INCREMENT=n | 5.0+ 支援 | 支援 | 不支援 | 不支援 |
| ALTER TABLE 重置起始值 | 支援 | 5.0+ 支援 | 支援 | 不支援 | 不支援 |
| 複合索引多序列 | 支援 | 不支援 | 不支援 | 支援 | 不支援 |
| 持久化計數器 | .MYI 檔案 | In-memory + redo log | 僅記憶體 | .db 檔案 | 僅附加寫入 |
CREATE TABLE `multi_seq` (
`group_id` INT NOT NULL,
`seq` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`data` VARCHAR(100),
PRIMARY KEY (`group_id`, `seq`) -- 複合主鍵,seq 為最後一列
) ENGINE=MyISAM;
INSERT INTO `multi_seq` (`group_id`, `data`) VALUES (1, 'A'), (1, 'B'), (2, 'X'), (2, 'Y');
-- group_id=1 序列:1,2 | group_id=2 序列:1,2 互不干擾
InnoDB 不支援此特性,需改用分表或應用層號段分配。
INSERT ... VALUES (),(),() 返回第一行自增值LAST_INSERT_ID(expr) 設定下一次返回值,實現自定義步長序列TRUNCATE TABLE / DELETE FROM table(無 WHERE)會重置自增計數器。保留序列請用 DELETE FROM table WHERE 1 強制逐行刪除auto_increment_increment + auto_increment_offset 錯開序列mysqldump 包含 AUTO_INCREMENT=xxx,還原後新插入從 xxx+1 開始,若需銜接舊序列需手動 ALTER TABLE ... AUTO_INCREMENT=新值CREATE TABLE `seq_global` (`id` BIGINT UNSIGNED NOT NULL) ENGINE=InnoDB;
INSERT INTO `seq_global` VALUES (0);
-- 取號
UPDATE `seq_global` SET `id` = LAST_INSERT_ID(`id` + 1);
SELECT LAST_INSERT_ID(); -- 返回新 ID
-- 步長 100 號段分配(分散式服務適用)
UPDATE `seq_global` SET `id` = LAST_INSERT_ID(`id` + 100);
SELECT LAST_INSERT_ID(); -- 返回號段起始值,應用層本地 +1 分配
優點:無表鎖、無事務、高併發、彈性步長。缺點:單點寫入(可改用多序列表分片)。
ALTER TABLE `t` DROP `id`;
ALTER TABLE `t` ADD `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
警告:外鍵關聯表會報錯,需先刪除外鍵。生產環境極不建議,破壞審計追蹤與資料關聯完整性。
AUTO_INCREMENT 不只是「自動加 1」。深度理解引擎差異、掌握 LAST_INSERT_ID() 進階用法、建立避坑檢查清單,才能在高併發、分散式、長期演進的系統中穩健落地。選對引擎、定好類型、備好號段策略——這才是專業工程師的態度。