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

MySQL 更新 TEXT 字段報 "Row size too large" 錯誤:根因與 Row_Format 解決方案

     編輯:MySQL 資料庫相關知識

在 InnoDB 表中更新 TEXT/BLOB 字段時,遇到 Error 1118: Row size too large (> 8126),明明字段類型是 TEXT(理應溢出頁存儲),卻仍報行大小超限。本文深度剖析 ROW_FORMAT、innodb_file_format 與溢出頁存儲機制的交互關系,給出徹底解決方案。

錯誤現場還原

-- 表結構
CREATE TABLE `t` (
  `id` INT PRIMARY KEY,
  `content` TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 更新一條超長文本(~10KB)
UPDATE `t` SET `content` = REPEAT('a', 10000) WHERE `id` = 1;

-- 報錯
Error Code: 1118. Row size too large (> 8126). 
Change some columns to TEXT or BLOBs

核心機制:ROW_FORMAT 決定溢出行為

根因:建表時未顯式指定 ROW_FORMAT

雖然配置了 innodb_file_format = Barracuda,但 InnoDB 為兼容舊版,建表默認仍用 Antelope 格式的 Compact 行格式,除非顯式指定:

-- 官方文檔原文:
-- "tables created with the InnoDB Plugin use the prefix format (Antelope/Compact),
-- unless ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED is specified"

因此表實際使用 ROW_FORMAT=COMPACT,TEXT 列前 768 字節存放在頁內,超過 8126 字節(所有列頁內部分之和)即報錯。

解決方案

方案一:建表時顯式指定 Dynamic(推薦,源頭治理)

CREATE TABLE `t` (
  `id` INT PRIMARY KEY,
  `content` TEXT
) ENGINE=InnoDB 
ROW_FORMAT=DYNAMIC  -- 關鍵!
DEFAULT CHARSET=utf8mb4;
  • DYNAMIC:Barracuda 格式,大字段完全溢出頁,頁內僅存 20 字節指針,行大小極小,幾乎不受 8126 限制。
  • COMPRESSED:在 Dynamic 基礎上啟用頁壓縮(zlib),存儲更省,CPU 稍增。

方案二:現有表在線變更 ROW_FORMAT(MySQL 5.6+)

ALTER TABLE `t` ROW_FORMAT=DYNAMIC;
-- 或
ALTER TABLE `t` ROW_FORMAT=DYNAMIC, ALGORITHM=INPLACE, LOCK=NONE;  -- 5.6+ 在線 DDL,不鎖表

執行後需 重新插入/更新數據 才會按新格式存儲(舊行不會自動重組)。

方案三:全局默認調整(MySQL 5.7+)

[mysqld]
innodb_file_format = Barracuda
innodb_file_per_table = ON
innodb_default_row_format = DYNAMIC  -- 5.7 新增,新建表默認 Dynamic

8.0 已移除 innodb_file_format,默認即為 Barracuda + Dynamic。

驗證表行格式

SHOW TABLE STATUS LIKE 't'\G
-- 關注 Row_format 列:Dynamic / Compact / Compressed

-- 或查詢信息模式
SELECT NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'db/t';

避坑指南

  1. 多 TEXT 列表:單表超過 10 個 TEXT/BLOB 列,即使 Dynamic 也可能因指針累積超限。拆分為多表或合併為 JSON。
  2. 報錯誤導性:Change some columns to TEXT or BLOBs 提示誤導(字段已是 TEXT),5.1.61+ 優化為 Row size too large (> 8126). Consider changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC/COMPRESSED。
  3. innodb_strict_mode=ON(默認開啟)會在建表/插入時嚴格檢查行大小,關閉可暫時繞過但極不推薦,會導致數據寫入失敗或損壞。

總結

Row size too large 核心原因是表行格式為 Compact(Antelope),導致大字段前綴存頁內。徹底解決:建表/ALTER 指定 ROW_FORMAT=DYNAMIC,配合 innodb_default_row_format=DYNAMIC 全局生效。升級至 MySQL 8.0 可一勞永逸獲得現代默認值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
File FormatRow Format首部存儲溢出閾值備註
Antelope (舊)Compact / Redundant前 768 字節~768 字節MySQL 5.5 默認
Barracuda (新)Dynamic / Compressed僅 20 字節指針~40 字節MySQL 5.7+ 默認,真正的溢出頁