AUTO_INCREMENT 是 MySQL 最常用的主鍵生成策略,但 MyISAM 與 InnoDB 在自增值持久化與重啟後行為上存在關鍵差異。本文透過實測案例,深度剖析兩大引擎的自增機制差異與背後原理。
AUTO_INCREMENT PRIMARY KEY 的測試表mysql> CREATE TABLE test_myisam (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name CHAR(5)
) ENGINE=MyISAM;
mysql> INSERT INTO test_myisam (name) VALUES ('a'), ('b'), ('c');
mysql> INSERT INTO test_myisam (name) SELECT name FROM test_myisam; -- 複製插入
mysql> SELECT * FROM test_myisam;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | a |
| 5 | b |
| 6 | c |
+----+------+
mysql> DELETE FROM test_myisam WHERE id=6;
mysql> INSERT INTO test_myisam (name) VALUES ('d');
mysql> SELECT * FROM test_myisam;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | a |
| 5 | b |
| 7 | d | <-- 新 ID 為 7 (原最大值 6 + 1)
+----+------+
即使刪除最大 ID,**下一次插入仍使用「歷史最大值 + 1」**。此值寫入資料檔案,重啟服務不影響。
mysql> CREATE TABLE test_innodb (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name CHAR(5)
) ENGINE=InnoDB;
mysql> INSERT INTO test_innodb (name) VALUES ('a'), ('b'), ('c');
mysql> SELECT * FROM test_innodb;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
+----+------+
mysql> DELETE FROM test_innodb WHERE id=3;
mysql> INSERT INTO test_innodb (name) VALUES ('d');
mysql> SELECT * FROM test_innodb;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 4 | d | <-- 新 ID 為 4 (記憶體中最大值 3 + 1)
+----+------+
mysql> DELETE FROM test_innodb WHERE id=4;
mysql> EXIT;
$ sudo service mysql restart
mysql> INSERT INTO test_innodb (name) VALUES ('z');
mysql> SELECT * FROM test_innodb;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | z | <-- 新 ID 為 3 (當前表中最大值 2 + 1)
+----+------+
| 行為場景 | MyISAM | InnoDB (未重啟) | InnoDB (重啟後) |
|---|---|---|---|
| 刪除最大 ID 後插入 | 歷史最大值 + 1 | 記憶體最大值 + 1 | 當前表最大值 + 1 |
| 持久化位置 | 資料檔案 (.MYD) | 記憶體 (InnoDB 內部計數器) | 重啟後從表掃描重建 |
| 重啟影響 | 無影響 | — | 計數器重置為 MAX(id)+1 |
.MYD 資料檔案MAX(id) 重建redo log 持久化自增值,重啟後從 redo log 恢復,行為更接近 MyISAM-- 建立測試表 CREATE TABLE t_auto (id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t_auto VALUES (), (), (); -- ID 1,2,3 DELETE FROM t_auto WHERE id=3; -- 重啟 MySQL 服務 -- 再次插入觀察新 ID INSERT INTO t_auto VALUES (); SELECT * FROM t_auto;
理解引擎層面的自增機制差異,能幫助你在架構設計、遷移升級、故障排查時做出正確決策,避免隱性 Bug 影響業務穩定性。