開發測試階段報錯 Duplicate entry '127' for key 1 或 '32767',乍看像主鍵衝突,實則是 自增列數據類型範圍耗盡。本文詳細列出 MySQL 整數類型範圍、溢出癥狀、定位方法與修復方案。
Invalid Query: Duplicate entry '127' for key 1
SQL: INSERT INTO kq_news (Title,Author,Type,Content,IsDel,Adate,Range,Lang)
VALUES ('捐款活動','yuanying','3','','0',NOW(),'2','cn')
表結構中 id TINYINT AUTO_INCREMENT PRIMARY KEY,插入第 128 條時嘗試生成 128,超出 TINYINT UNSIGNED 上限 255?實際報 127 說明是 有符號 TINYINT(上限 127)。
| 類型 | 存儲字節 | 有符號範圍 | 無符號範圍 | 適用場景 |
|---|---|---|---|---|
| TINYINT | 1 | -128 ~ 127 | 0 ~ 255 | 極小枚舉、狀態碼、布爾替代 |
| SMALLINT | 2 | -32,768 ~ 32,767 | 0 ~ 65,535 | 小型字典表、配置項 ID |
| MEDIUMINT | 3 | -8,388,608 ~ 8,388,607 | 0 ~ 16,777,215 | 中型業務表主鍵(百萬級) |
| INT / INTEGER | 4 | -2,147,483,648 ~ 2,147,483,647 | 0 ~ 4,294,967,295 | 通用主鍵標準選擇(21 億) |
| BIGINT | 8 | -9.22e18 ~ 9.22e18 | 0 ~ 1.84e19 | 超大規模、分布式 ID、雪花算法 |
| 報錯 Duplicate entry 值 | 對應類型 | 有/無符號 | 已插入行數 |
|---|---|---|---|
| 127 | TINYINT | SIGNED | 127 |
| 255 | TINYINT | UNSIGNED | 255 |
| 32,767 | SMALLINT | SIGNED | 32,767 |
| 65,535 | SMALLINT | UNSIGNED | 65,535 |
| 2,147,483,647 | INT | SIGNED | 21.4 億 |
SHOW CREATE TABLE tbl_name\G 查看 id 定義。SELECT MAX(id) FROM tbl_name;-- 方案 A:直接擴大類型(MySQL 5.6+ Online DDL)
ALTER TABLE tbl_name MODIFY COLUMN id INT UNSIGNED AUTO_INCREMENT;
-- 方案 B:大表零停機(pt-online-schema-change)
pt-online-schema-change --alter "MODIFY COLUMN id BIGINT UNSIGNED AUTO_INCREMENT" D=db,t=tbl_name --execute
ALTER TABLE tbl_name AUTO_INCREMENT = 1000;BIGINT UNSIGNED 或 INT UNSIGNED:除非極確定行數永不超百萬,否則別用 SMALLINT/TINYINT 做主鍵。SELECT MAX(id)/4294967295 * 100 AS pct FROM tbl; 納入巡檢。BIGINT,單表自增預留 10 倍增長空間。DELETE 刪除最大 ID 行後,MyISAM 會重用該 ID,InnoDB 不重用(內存計數器單調遞增)。重啟後 InnoDB 重新計算 MAX(id)+1,可能導致自增值「倒退」但不衝突。若業務強依賴 ID 單調遞增不可復用,請用 BIGINT + 雪花算法生成。