ORDER BY卡住主因是排序中途落盘引发磁盘临时表、IO激增与锁等待链式反应,根本解法是修复索引缺失或失效问题,而非盲目调大sort_buffer_size等参数。
为什么ORDER BY一跑就卡住还报超时
根本不是“排序慢”,而是排序中途被迫落盘,触发磁盘临时表 + 大量IO + 锁等待链式反应。你看到的 ERROR 1205 或 Lock wait timeout exceeded,往往只是表象——背后是 Using filesort 和 Using temporary 同时出现,且 Created_tmp_disk_tables 暴涨。
- EXPLAIN里同时出现
Using filesort和Using temporary:说明MySQL既要排序又要建临时表,内存不够就全写磁盘 -
SHOW GLOBAL STATUS LIKE 'Sort_merge_passes'每秒涨 > 1:sort_buffer_size 确实撑不住了 -
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables'和Created_tmp_tables比值 > 15%:临时表已频繁落盘,ibtmp1开始膨胀
别急着调 sort_buffer_size,先看索引有没有生效
90% 的 Using filesort 根本不靠调参解决——是 ORDER BY 字段没索引,或索引被绕过。调大 buffer 只是给没索引的查询续命,反而让锁持有时间更长。
- 执行
EXPLAIN SELECT ... ORDER BY created_at,检查key列是否为NULL;如果是,说明没走索引 - 字段类型不一致(比如
created_at是DATETIME,但 WHERE 里传的是字符串'2026-07-01')会触发隐式转换,索引失效 - 函数包裹:
ORDER BY UPPER(name)、ORDER BY DATE(created_at),一律无法走索引,强制 filesort - 联合索引顺序错:要
ORDER BY status, created_at,却只建了(created_at, status),用不上
tmp_table_size 和 max_heap_table_size 必须相等,且得按并发算
这两个参数取较小值作为单个临时表内存上限。设成不一致(比如 tmp_table_size = 512M,max_heap_table_size = 64M),实际就是 64MB —— 再大的中间结果也立刻落盘。
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
- 在
/etc/my.cnf的[mysqld]段里显式写两行,值完全一样:tmp_table_size = 128M,max_heap_table_size = 128M - 重启后必须验证:
SELECT @@tmp_table_size, @@max_heap_table_size;,确认返回值相等且单位是字节(128M ≈ 134217728) - 别按总内存算:64GB 机器 ≠ 能设 2G。真实压力是
max_connections × 单次最大临时表,建议上限 ≤ 物理内存的 15%,比如 200 并发下,单 session 最多设 64M~128M
MySQL 8.0+ 必须设 internal_tmp_mem_storage_engine = TempTable
老版本默认用 MEMORY 引擎,一行 TEXT 就爆内存;MySQL 8.0+ 默认改用 TempTable,支持动态行格式、TEXT/BLOB off-page 存储、内存池管理——同样数据量比 MEMORY 少占 30%~50% 内存,且超限时才自动落盘。
- 查当前设置:
SELECT @@internal_tmp_mem_storage_engine;,如果不是TempTable,就得配 - 配置文件加一行:
internal_tmp_mem_storage_engine = TempTable - 这个设置不重启也能生效(动态变量),但建议配合
tmp_table_size和max_heap_table_size一起调,否则没意义
真正卡住事务的,从来不是单条 SQL 多慢,而是它把临时表打到磁盘、拖长锁持有时间、再被其他连接排队堵死。索引没建好之前,所有参数调整都是在给火上浇油。