sort_buffer_size并非越大越好,盲目调高易引发OOM;它按需分配、每连接独占,建议会话级设为4MB而非全局调整,并优先优化索引避免filesort。

MySQL排序内存不足报 Out of memory 怎么调 sort_buffer_size
直接说结论:sort_buffer_size 不是越大越好,盲目调高反而容易触发 OOM;它只在需要排序的语句中按需分配,且每个连接独占一份。常见错误是把它设成 256MB 甚至 1GB,结果并发稍高就炸内存。
实操建议:
-
sort_buffer_size是会话级变量,建议在 SQL 执行前用SET SESSION sort_buffer_size = 4194304;(即 4MB)临时调整,而不是全局改死 - 查当前值用
SHOW VARIABLES LIKE 'sort_buffer_size';,注意单位是字节 —— 默认通常是 262144(256KB),不是 MB - 如果语句带
ORDER BY或GROUP BY且没走索引,才会真正用到这个 buffer;有合适索引时,它基本不生效 - 线上环境慎用全局设置,尤其连接池大的服务;一个连接占 32MB,100 个并发就是 3.2GB 白白预留
为什么 ORDER BY 慢还爆内存?先看执行计划有没有 Using filesort
出现 Out of memory 前,往往先看到慢查询日志里有 Using filesort —— 这说明 MySQL 没法用索引完成排序,得把数据捞出来再排,这时候才真正依赖 sort_buffer_size。
实操建议:
- 用
EXPLAIN SELECT ... ORDER BY ...看Extra列,确认是否真有Using filesort - 优先加复合索引覆盖排序字段,比如
ORDER BY status, created_at就建INDEX(status, created_at),比调 buffer 管用十倍 - 如果字段类型是
TEXT或VARCHAR(2000),即使有索引,也可能因长度超限退化为 filesort —— 这时候要配合innodb_large_prefix=ON和更合理的字段设计
sort_buffer_size 和 read_rnd_buffer_size 容易搞混,它们到底谁管什么
sort_buffer_size 只负责「排序阶段」的内存,而 read_rnd_buffer_size 是排序后回表取数据用的 —— 如果 ORDER BY 字段不在索引里,MySQL 排完序得到主键 ID,还得一个个回去读完整行,这时就靠后者。
MySQL 数据库管理技能,能够通过自然语言查询和管理数据库,支持 SELECT/INSERT/UPDATE/DELETE、表管理、备份恢复等操作。当用户提及 MySQL、数据库查询、建表或数据备份时使用此技能。
实操建议:
- 当
Using filesort后还看到Using temporary,大概率是两者都不够,但优先调sort_buffer_size;只有确认排序完成、回表变慢时,才考虑动read_rnd_buffer_size -
read_rnd_buffer_size默认值通常比sort_buffer_size小(比如 256KB vs 2MB),但它也按连接分配,同样不能无脑拉高 - 这两个 buffer 都不会被复用,一次查询结束就释放,不存在“缓存”效果
除了 buffer,还有哪些配置会间接导致排序内存压力
真正压垮内存的,常常不是 sort_buffer_size 本身,而是它和其他参数叠加后的组合效应。比如大结果集 + 多连接 + 全局 buffer 过高,三者一碰就崩。
实操建议:
- 检查
max_connections是否远超实际需要,它决定了最大可能的 buffer 占用总量 -
tmp_table_size和max_heap_table_size控制内存临时表大小,如果GROUP BY或子查询生成了大临时表,也会抢内存 —— 它们和sort_buffer_size是并列消耗项 - 开启
log_queries_not_using_indexes,快速定位哪些查询在默默触发 filesort - 监控
Sort_merge_passes状态值(用SHOW STATUS LIKE 'Sort_merge_passes';),持续升高说明排序频繁落磁盘,buffer 确实不够或索引没用好
最常被忽略的一点:buffer 调整必须配合业务查询模式验证。同样的 4MB,在单条小查询里绰绰有余,在一条扫百万行的报表 SQL 里可能刚够塞下两页数据。别信“别人家的值”,只信自己压测时的 Sort_merge_passes 和 OOMKilled 日志。

















