AUTO_INCREMENT 是生成代理主鍵的核心機制,但不同存儲引擎(MyISAM、InnoDB、Memory、BDB)在初始值設置、最大值重用、復合索引序列、持久化語義上存在顯著差異。本文系統梳理各引擎行為,並給出生產環境修改自增值、防重用、替代方案的最佳實踐。
| 特性 | MyISAM | InnoDB | Memory (HEAP) | BDB |
|---|---|---|---|---|
建表指定初始值 AUTO_INCREMENT=n | ✓ | ✗ (5.7+ 支持) | ✓ | ✗ |
ALTER TABLE t AUTO_INCREMENT=n 修改起值 | ✓ | ✗ (5.7+ 支持) | ✓ | ✗ |
| 最大值刪除後是否重用 | ✓ 重用 | ✗ 不重用 | ✗ 不重用 | ✓ 重用 |
復合索引多序列 PRIMARY KEY(a, auto_id) | ✓ | ✗ | ✗ | ✓ |
| 持久化計數器存儲 | .MYI 文件 | 內存 + Redo Log (8.0 持久化到數據字典) | 僅內存,重啟歸零 | .db 文件 |
innodb_autoinc_lock_mode(0=傳統表鎖、1=連續鎖默認、2=交錯鎖高併發)mysql.innodb_table_stats,重啟不再重掃 B+TreeALTER TABLE t AUTO_INCREMENT = 1000(需 > 當前最大值)UNSIGNED 推薦,翻倍正數範圍NOT NULL 必須-- 5.7.9+ / 8.0 直接修改(需大於當前最大值)
ALTER TABLE t AUTO_INCREMENT = 100000;
-- 老版本或需縮小值:重建表
CREATE TABLE t_new LIKE t;
ALTER TABLE t_new AUTO_INCREMENT = 1000;
INSERT INTO t_new SELECT * FROM t;
RENAME TABLE t TO t_old, t_new TO t;
BIGINT UNSIGNED(1.84e19),單表百年不枯竭SHOW TABLE STATUS LIKE 't'\G 中 Auto_increment 接近上限報警-- TRUNCATE / DELETE 無 WHERE 會重置自增計數器
-- 保留計數器的刪除寫法(逐行評估,慢但保留)
DELETE FROM t WHERE 1; -- 或 WHERE id > 0
innodb_autoinc_lock_mode=2(交錯鎖,Statement-based 複制不安全)SELECT LAST_INSERT_ID() 配合 INSERT ... VALUES (),(),()CREATE TABLE seq (id INT UNSIGNED NOT NULL);
INSERT INTO seq VALUES (0);
-- 獲取下一值(步長可控)
UPDATE seq SET id = LAST_INSERT_ID(id + 1);
SELECT LAST_INSERT_ID(); -- 返回新值
-- 步長 10
UPDATE seq SET id = LAST_INSERT_ID(id + 10);
SELECT LAST_INSERT_ID();
優點:無表鎖、無事務、可定製步長、多計數器共存。
| 誤區 | 事實 |
|---|---|
| 插入 0 等同插入 NULL | 0 會被當作具體值寫入,若列有 NOT NULL 則報錯;只有 NULL 觸發自增生成 |
| REPLACE 不影響自增值 | REPLACE 基於主鍵/唯一鍵刪除舊行再插入,若自增列不在 WHERE 中,會生成新值 |
| LAST_INSERT_ID() 是全局的 | 僅限當前會話,線程隔離,安全 |