首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL Row size too large 65535 錯誤:原因深度解析與 varchar 轉 text 解決方案

     編輯:MySQL 資料庫相關知識

錯誤現象

ERROR 1118 (42000): Row size too large. 
The maximum row size for the used table type, not counting BLOBs, is 65535

建表/加列/改列類型時拋出,阻塞 DDL 執行。

根因:單行非大字段存儲超過 65535 字節

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 (溢出頁存儲)

原理

  • TEXT / BLOB / VARCHAR(>768字節) → **溢出頁存儲**,行內僅留 20 字節指針
  • 行存儲大幅降低,繞過 65535 限制

操作步驟

-- 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;

varchar 長度選型建議表

業務長度推薦類型行內存儲索引支援
≤ 255 字符VARCHAR(n)是 (≤768字節)完整索引
256 ~ 768 字節VARCHAR(n)是完整索引
769 ~ 65535 字符VARCHAR(n) / TEXT否 (溢出頁)前綴索引 (如 idx(col(191)))
> 65535 字符TEXT / MEDIUMTEXT / LONGTEXT否全文索引 / 前綴索引

避坑指南

  1. 預防勝於治療:設計階段按「最小足夠原則」定長度,拒絕通用 VARCHAR(255) / VARCHAR(500)
  2. 字符集影響:utf8mb4 下 1 字符 = 4 字節,VARCHAR(191) = 764 字節 (行內),VARCHAR(192) = 768 字節 (臨界點)
  3. 索引長度限制:單列索引 ≤ 767 字節 (InnoDB 默認),utf8mb4 下最長索引 191 字符
  4. TEXT 不能有默認值:DEFAULT 'xxx' 報錯,應用層處理
  5. TEXT 不能全長度索引:只能前綴索引,精確查詢走不了索引

緊急繞過方案 (不修改結構)

# my.cnf 強制行格式 (風險:可能導致數據截斷/報錯)
[mysqld]
innodb_strict_mode=OFF

⚠️ **極不推薦生產環境使用**,僅用於緊急數據搶救後立即修正結構。

總結

Row size too large 本質是**行內存儲預算超支**。核心對策:**長字段溢出頁化 (TEXT/BLOB)** + **合理定長度** + **前綴索引**。定期掃描 INFORMATION_SCHEMA.COLUMNS 發現超長 VARCHAR,提前治理,避免 DDL 突發失敗阻塞發布。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved