如何一键备份你的QQ空间历史说说?GetQzonehistory终极指南
2026/4/28 8:26:39
“所有列总和 ≤ 65,535 字节” 是MySQL Server 层对单行最大长度的硬性限制,与存储引擎(如 InnoDB、MyISAM)无关。
当 MySQL Server 处理一行数据时(如返回客户端、写 binlog),使用统一的内部行格式(Row-based Format),其关键设计:
✅本质:
这是MySQL 协议层的限制,确保行数据能被网络包(max_allowed_packet)和内部缓冲区安全处理。
| 层级 | 限制 | 说明 |
|---|---|---|
| MySQL Server 层 | 65,535 字节/行 | 所有列定义长度总和 |
| InnoDB 层 | ≈8,000 字节/页(主键页内) | 实际存储限制,可通过溢出页突破 |
⚠️关键点:
即使 InnoDB 能存 4GB 的LONGTEXT,MySQL Server 在处理该行时仍受 65,535 字节限制——但仅针对非大对象列。
CHAR,VARCHAR,BINARY,VARBINARY,TINYBLOB,TINYTEXTBLOB,TEXT,MEDIUMBLOB,MEDIUMTEXT,LONGBLOB,LONGTEXT,JSON💡规则:
只有“可完全存入行内”的列才计入限制;大对象(> 255 字节)自动转为指针,不占此配额。
\sum (\text{列声明长度} \times \text{字符集最大字节}) \leq 65,535utf8mb3:1 字符 = 最多 3 字节utf8mb4:1 字符 = 最多 4 字节-- 案例 1:utf8mb4 下 VARCHAR(16383) → 16383 * 4 = 65,532 字节(合法)CREATETABLEt1(aVARCHAR(16383)CHARACTERSETutf8mb4);-- 案例 2:两列 VARCHAR(32767) → 32767*2*2 = 131,068 > 65,535(报错)CREATETABLEt2(aVARCHAR(32767),bVARCHAR(32767));-- ERROR 1118 (42000): Row size too large...-- 合法:单列 TEXT 不计入 65,535CREATETABLEt3(aTEXT);-- 合法:VARCHAR(20000) + TEXT → 仅 VARCHAR 计入CREATETABLEt4(aVARCHAR(20000)CHARACTERSETutf8mb4,-- 20000*4=80,000 > 65,535?bTEXT);-- ❌ 仍会报错!因为 VARCHAR(20000) 已超限✅正确做法:
将大字段声明为TEXT,而非VARCHAR:CREATETABLEt5(aTEXT,-- 不计入 65,535bTEXT);
CREATETABLEwide_table(col1VARCHAR(10000),col2VARCHAR(10000),...col7VARCHAR(10000)-- 7*10000=70,000 > 65,535);-- ERROR 1118: Row size too large解决方案:
CREATETABLEwide_table(col1TEXT,col2TEXT,...);-- 声明 VARCHAR(20000) 在 utf8mb3 下合法(20000*3=60,000)-- 但在 utf8mb4 下非法(20000*4=80,000)ALTERTABLEtCONVERTTOCHARACTERSETutf8mb4;-- 可能失败!解决方案:
MAX_VARCHAR = FLOOR(65535 / max_bytes_per_char)SETGLOBALinnodb_file_format=Barracuda;CREATETABLEt(...)ROW_FORMAT=DYNAMIC;CREATETABLEuser_core(id,name,email);CREATETABLEuser_profile(id,bio,settings,...);CREATETABLEt(idINT,dataJSON);-- JSON 不计入 65,535SHOWTABLESTATUSLIKE'your_table';-- 关注 Row_format, Avg_row_lengthSELECTCOLUMN_NAME,CHARACTER_MAXIMUM_LENGTH,CHARACTER_OCTET_LENGTH-- 实际字节上限FROMinformation_schema.COLUMNSWHERETABLE_SCHEMA='db'ANDTABLE_NAME='table';