AUTO_INCREMENT 是 MySQL 中最常用的主鍵生成策略,看似簡單卻藏著許多開發者易忽視的行為細節。本文將從核心機制、典型陷阱、進階配置三個維度深度剖析。
最關鍵的特性:**自增值只增不減,刪除資料不會回收已用 ID**。
CREATE TABLE t (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
INSERT INTO t (name) VALUES ('A'), ('B'), ('C'); -- id: 1,2,3
DELETE FROM t WHERE id = 1; -- 刪除 id=1
INSERT INTO t (name) VALUES ('D'); -- 新資料 id=4,而非 1!
這設計是為了:
INT 最大值約 21 億,BIGINT 約 922 京。高頻寫入系統(如日誌、物聯網)若用 INT 易耗盡。
對策:主鍵預設使用 BIGINT,或評估業務增長改用 BIGINT UNSIGNED。
INSERT INTO t (id, name) VALUES (100, 'X'); -- 手動插入大 ID
INSERT INTO t (name) VALUES ('Y'); -- 下一個自動 ID 為 101 (MySQL 8.0+ 行為)
-- 舊版本可能仍為 4,視 innodb_autoinc_lock_mode 而定
對策:避免業務邏輯手動指定自增主鍵值;若必須指定,插入後執行 ALTER TABLE t AUTO_INCREMENT = 101 同步計數器。
START TRANSACTION;
INSERT INTO t (name) VALUES ('T1'); -- 分配 id=5
INSERT INTO t (name) VALUES ('T2'); -- 分配 id=6
ROLLBACK; -- 兩筆都回滾,但 id 5、6 永久「消失」
這是 InnoDB 預設行為(innodb_autoinc_lock_mode = 2),為換取高並發插入效能。空洞不可避免,業務勿依賴 ID 連續性。
TRUNCATE TABLE t; 會將 AUTO_INCREMENT 重置為初始值(通常為 1),DELETE FROM t; 則保留當前最大值+1。
-- 查看
SHOW TABLE STATUS LIKE 't'\G
-- 欄位 Auto_increment 即為下一個將分配的值
-- 手動設定 (需大於現有最大值)
ALTER TABLE t AUTO_INCREMENT = 10000;
| 值 | 模式 | 特性 | 適用場景 |
|---|---|---|---|
| 0 | Traditional | 表級鎖,序列化分配,ID 連續 | 主從複制用 Statement 格式 Binlog 時必須 |
| 1 | Consecutive (預設 5.7 前) | 簡單插入用輕量鎖,批量插入用表鎖 | 兼顧效能與連續性 |
| 2 | Interleaved (預設 8.0+) | 無鎖分配,高並發,ID 可能不連續 | 高並發寫入、Row 格式 Binlog、生產環境推薦 |
auto_increment_increment、auto_increment_offset 實現多主避免衝突。BIGINT UNSIGNED,預留足夠空間。innodb_autoinc_lock_mode=2 (MySQL 8.0 預設)。Auto_increment 值接近型別上限時預警擴容。AUTO_INCREMENT 是為單機高效插入設計的妥協產物,理解其「只增不減、允許空洞、不可回滾」的本質,才能在架構演進中做出正確選擇。