ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535
建表/加列/改列類型時拋出,阻塞 DDL 執行。
InnoDB 頁大小 16KB,但**行存儲上限 65535 字節** (約 64KB),**不含溢出頁的 BLOB/TEXT/VARCHAR(>768字節) 實際數據**,只含其 20 字節指針。
行存儲大小 = 固定開銷 (約 5-10 字節) + 所有定長列大小 (CHAR, INT, BIGINT 等) + 所有變長列指針大小 (VARCHAR/VARBINARY ≤ 768 字節時存行內,指針 1-2 字節) + 所有 NULL 列位圖 (列數/8 字節) + 所有變長列長度列表 (變長列數 × 2 字節) ≤ 65535 字節
VARCHAR(255) / VARCHAR(500) 列 (行內存儲)CHAR(255) 定長列過多TEXT / BLOB / VARCHAR(>768字節) → **溢出頁存儲**,行內僅留 20 字節指針-- 1. 識別長字段
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='db' AND TABLE_NAME='t'
AND (DATA_TYPE IN ('varchar','char') AND CHARACTER_MAXIMUM_LENGTH > 255);
-- 2. 修改為 TEXT (需鎖表重建,大表用 pt-online-schema-change)
ALTER TABLE t MODIFY COLUMN long_col TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 3. 或批量生成修改腳本
SELECT CONCAT('ALTER TABLE `', TABLE_NAME, '` MODIFY `', COLUMN_NAME, '` TEXT;')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='db' AND DATA_TYPE='varchar' AND CHARACTER_MAXIMUM_LENGTH > 500;
| 業務長度 | 推薦類型 | 行內存儲 | 索引支援 |
|---|---|---|---|
| ≤ 255 字符 | VARCHAR(n) | 是 (≤768字節) | 完整索引 |
| 256 ~ 768 字節 | VARCHAR(n) | 是 | 完整索引 |
| 769 ~ 65535 字符 | VARCHAR(n) / TEXT | 否 (溢出頁) | 前綴索引 (如 idx(col(191))) |
| > 65535 字符 | TEXT / MEDIUMTEXT / LONGTEXT | 否 | 全文索引 / 前綴索引 |
VARCHAR(255) / VARCHAR(500)VARCHAR(191) = 764 字節 (行內),VARCHAR(192) = 768 字節 (臨界點)DEFAULT 'xxx' 報錯,應用層處理# my.cnf 強制行格式 (風險:可能導致數據截斷/報錯) [mysqld] innodb_strict_mode=OFF
⚠️ **極不推薦生產環境使用**,僅用於緊急數據搶救後立即修正結構。
Row size too large 本質是**行內存儲預算超支**。核心對策:**長字段溢出頁化 (TEXT/BLOB)** + **合理定長度** + **前綴索引**。定期掃描 INFORMATION_SCHEMA.COLUMNS 發現超長 VARCHAR,提前治理,避免 DDL 突發失敗阻塞發布。