text/blob 字段本身不直接报 out of memory 错误,但会强制触发磁盘临时表、额外随机 i/o 和整页加载,导致内存被悄悄耗尽;根本原因是 mysql 的 memory 引擎不支持 text/blob,只要排序或分组涉及此类字段,即使 tmp_table_size 足够大也会落盘。

TEXT/BLOB 字段本身不会直接报 Out of memory 错误,但会让 MySQL 在排序、分组、临时表、全字段读取时悄悄吃光内存——根本原因是它们强制触发磁盘临时表、额外随机 I/O 和整页加载,而不是你配置的 sort_buffer_size 或 tmp_table_size 不够大。
为什么 ORDER BY 或 GROUP BY TEXT 会爆内存
MySQL 的 MEMORY 引擎压根不支持 TEXT/BLOB 类型。只要语句里出现 ORDER BY content、GROUP BY SUBSTRING(content, 1, 50),甚至 ORM 自动生成的 SELECT * FROM article ORDER BY created_at(哪怕没动 TEXT 字段),优化器也会直接放弃内存临时表,转而创建磁盘临时表。
- 即使你把
tmp_table_size和max_heap_table_size都设到 1G,照样落盘 -
EXPLAIN显示Using temporary; Using filesort,且type是ALL或key为NULL,基本就是 TEXT 拖累的 - 慢查询日志里
Rows_examined远大于Rows_sent,同时Sort_merge_passes持续上涨,说明正在反复读写磁盘临时文件
怎么确认某条记录真在用溢出页
不能只看字段类型是 TEXT 就断定用了溢出页;得结合行格式和实际内容长度判断。
- 运行
SHOW CREATE TABLE article\G,确认ROW_FORMAT是DYNAMIC还是COMPACT(COMPACT下超 768 字节就溢出) - 查真实长度:
SELECT LENGTH(content) FROM article WHERE id = 123;—— 如果结果 > 8000 且格式是DYNAMIC,基本进了溢出页 - 观察
SHOW PROFILE FOR QUERY N中的Handler_read_rnd_next:值异常高,说明频繁跳页读取溢出数据 - 不要依赖
INFORMATION_SCHEMA.INNODB_SYS_TABLES查溢出页计数,它滞后且不准;优先用实际读取行为反推
绕开 TEXT 参与内存操作的实操写法
核心不是“压缩”或“截断”,而是让排序、分组、JOIN 完全脱离 TEXT 字段本体。
- 把排序依据物化成独立列:
ALTER TABLE article ADD content_updated_at DATETIME NOT NULL DEFAULT '1970-01-01',应用层同步更新,然后ORDER BY content_updated_at - 对内容做轻量摘要并建索引:
ALTER TABLE article ADD content_md5 CHAR(32) AS (MD5(content)) STORED, ADD INDEX idx_content_md5 (content_md5) - 绝对避免
ORDER BY UPPER(content)或GROUP BY JSON_EXTRACT(content, '$.title')—— 函数调用既无法走索引,又把 TEXT 拖进临时表 - 查询时显式排除 TEXT:
SELECT id, title, status FROM article WHERE ...,详情页再用SELECT content FROM article_content WHERE id = ?单独拉
垂直拆分时最容易被忽略的细节
拆表不是改个 DDL 就完事;最常出问题的是事务边界和缓存一致性。
- 主表和内容表必须用同一事务更新,否则会出现“有头无身”:主表插入成功,内容表写入失败,后续
LEFT JOIN返回 NULL - ORM 层要禁用自动
SELECT *,否则 JPA/Hibernate 仍会尝试映射已删除的字段,抛SQLException或静默丢数据 - 备份脚本需同步处理两张表,否则恢复后外键关联断裂;mysqldump 要加
--skip-triggers --single-transaction避免锁表 - 如果旧数据要迁移,别用
INSERT INTO article_content SELECT id, content FROM article—— 大字段批量 INSERT 容易触发max_allowed_packet截断,必须分批次 + 应用层校验长度











