萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL Duplicate entry 錯誤根因:自增 ID 耗盡與類型上限解決方案

錯誤現象

Error: Duplicate entry '8181' for key 1
Errno: 1062

乍看是主鍵衝突,實則可能是 TINYINT/SMALLINT 自增 ID 達到類型上限。

整數類型上限回顧

類型有號上限無號上限
TINYINT127255
SMALLINT32,76765,535
MEDIUMINT8,388,60716,777,215
INT2,147,483,6474,294,967,295
BIGINT9.22E181.84E19

根因分析

Discuz! 早期版本使用 SMALLINT(6) UNSIGNED 作為 tid(主題 ID),上限 65,535。當主題數超過此值,自增嘗試寫入 65,536 失敗,MySQL 回報 Duplicate entry '65535' for key 1(實為溢位截斷回 65535 導致主鍵衝突)。

解決方案:修改欄位類型

ALTER TABLE `cdb_threads`
CHANGE `tid` `tid` INT(10) UNSIGNED NOT NULL DEFAULT '0' AUTO_INCREMENT;
  • 同步修改所有關聯表的外鍵欄位(cdb_posts.tid 等)。
  • 若為主鍵,需先 DROP PRIMARY KEY 再 ADD PRIMARY KEY,或用 MODIFY COLUMN(8.0+ 支援)。
  • 操作前務必完整備份。

預防檢查腳本

SELECT 
  TABLE_NAME, COLUMN_NAME, DATA_TYPE, COLUMN_TYPE,
  CASE 
    WHEN DATA_TYPE='tinyint'   THEN IF(COLUMN_TYPE LIKE '%unsigned%', 255, 127)
    WHEN DATA_TYPE='smallint'  THEN IF(COLUMN_TYPE LIKE '%unsigned%', 65535, 32767)
    WHEN DATA_TYPE='mediumint' THEN IF(COLUMN_TYPE LIKE '%unsigned%', 16777215, 8388607)
    WHEN DATA_TYPE='int'       THEN IF(COLUMN_TYPE LIKE '%unsigned%', 4294967295, 2147483647)
    WHEN DATA_TYPE='bigint'    THEN '~9E18'
  END AS max_value,
  AUTO_INCREMENT
FROM information_schema.COLUMNS
JOIN information_schema.TABLES USING (TABLE_SCHEMA, TABLE_NAME)
WHERE TABLE_SCHEMA = 'your_db'
  AND EXTRA = 'auto_increment'
ORDER BY max_value ASC;

定期執行,提前發現即將耗盡的自增欄位。

copyright © 萬盛學電腦網 all rights reserved