線上環境出現 Duplicate entry for key PRIMARY,經排查發現表內最大主鍵值大於自增計數器。人工調大 AUTO_INCREMENT 緊急恢復後,深入複現根因:Row 格式複制 + InnoDB + 自增主鍵 + 唯一鍵 + REPLACE INTO (LOAD DATA) 組合觸發主備切換後自增值不同步。
binlog_format = ROWLOAD DATA INFILE ... REPLACE 或 REPLACE INTOREPLACE 內部轉為 DELETE + INSERT,自增計數器 +1(如 5→6),新行主鍵為 6。REPLACE 記錄為 UPDATE_ROWS_EVENT(更新現有行主鍵為 6),不包含自增計數器變更。UPDATE,將舊行主鍵從 2 改為 6,**但 UPDATE 不會更新自增計數器**,備庫自增值停留在 5。INSERT 產生主鍵 5 → 主鍵衝突。-- 建表 CREATE TABLE test_autoinc ( id INT AUTO_INCREMENT, c1 INT, c2 VARCHAR(100), PRIMARY KEY (id), UNIQUE KEY (c1) ) ENGINE=InnoDB; -- 插入 5 筆,自增值變 6 INSERT INTO test_autoinc (c1,c2) VALUES (1,'abc'),(2,'abc'),(3,'abcdd'),(4,'abcdd'),(5,'abcdd'); -- SHOW CREATE TABLE → AUTO_INCREMENT=6 -- 主庫執行 REPLACE(c1=2 已存在) REPLACE INTO test_autoinc (c1,c2) VALUES (2,'eeee'); -- 影響 2 行:DELETE id=2 + INSERT id=6 -- 主庫自增值變 7,備庫自增值仍為 6(UPDATE 不更新自增) -- 主備切換後,新主庫自增值 6,表內最大 id=6 → 下次 INSERT 衝突
已提交 Bug #73563。生產環境規避:
REPLACE INTO / LOAD DATA REPLACE,改用 INSERT ... ON DUPLICATE KEY UPDATE(Binlog 記錄為 WRITE_ROWS + UPDATE_ROWS,自增值同步正確)。ALTER TABLE t AUTO_INCREMENT = (SELECT MAX(id)+1 FROM t);。核心教訓:Row 格式複制下,UPDATE 不傳播自增計數器。任何導致「主庫 DELETE+INSERT、備庫 UPDATE」的操作(REPLACE、LOAD DATA REPLACE、INSERT IGNORE 觸發唯一鍵衝突轉 UPDATE)均可能引發此問題。架構設計時務必評估複制格式與寫入模式的組合風險。