“The table is full”主因是tmp_table_size与max_heap_table_size中较小值过低,导致GROUP BY等操作的内存临时表溢出落盘,而非磁盘空间不足;二者须同步设为相同值(如256M),并检查ibtmp1是否异常膨胀。

为什么磁盘没满,MySQL 还报 The table is full
这不是磁盘空间告急,而是 MySQL 内部临时表或排序缓冲区超限了。最常见于 GROUP BY、ORDER BY、大结果集 JOIN 或 CREATE TABLE ... SELECT 场景——MySQL 试图把中间数据写进临时表,但默认配置太保守,哪怕磁盘有上百 GB 空闲,也会卡在几十 MB 就报错。
tmp_table_size 和 max_heap_table_size 必须同步调大
这两个参数共同限制内存中临时表的大小上限:只有两者都够大,MySQL 才允许把临时表保留在内存;任一偏小,就会强制落盘到 tmpdir 下的磁盘临时表(即 MYD/MYI 或 ibtmp1),而后者受 innodb_temp_data_file_path 或系统 tmpdir 分区容量约束。
- 必须让
tmp_table_size≤max_heap_table_size,否则前者实际生效值会被截断为后者 - 线上建议设为
256M起步(如SET GLOBAL tmp_table_size = 268435456),并同步改max_heap_table_size - 仅会话级生效的
SET SESSION不解决后台线程或长事务问题,需改全局 + 重启或持久化配置 - 修改后检查是否生效:
SELECT @@tmp_table_size, @@max_heap_table_size;
确认临时表到底落哪了:查 tmpdir 和 innodb_temp_data_file_path
执行 SHOW VARIABLES LIKE 'tmpdir';,看返回路径所在分区是否真满了(比如 /tmp 是独立 2GB 分区)。更隐蔽的是 InnoDB 自己的临时表空间:
- InnoDB 1.2+ 默认启用
innodb_temp_data_file_path = ibtmp1:12M:autoextend,它不断增长但不自动收缩,可能占满datadir所在磁盘 - 用
ls -lh $(mysql -Nse "SELECT @@datadir;")/ibtmp1查大小,若超 10GB 且业务无大临时操作,大概率是泄漏 - 该文件只能通过重启 MySQL 清空(关闭
innodb_fast_shutdown=0后重启),无法在线清理
快速验证和绕过:用 SQL_BIG_RESULT 或强制走磁盘临时表
如果只是某条 SQL 报错,不想动全局配置,可临时干预执行计划:
- 加提示让优化器预估结果集大,主动用磁盘临时表:
SELECT SQL_BIG_RESULT ... GROUP BY ... - 或反向抑制内存表,强制走磁盘:
SET SESSION tmp_table_size = 1024; SELECT ...(仅限调试,别长期用) - 但注意:磁盘临时表性能差一个数量级,且仍依赖
tmpdir空间,本质是转移问题而非解决 - 真正要查根因,用
EXPLAIN FORMAT=JSON看used_temp_tables和used_filesort是否高频出现
最易被忽略的是 ibtmp1 文件——它不显示在 SHOW TABLE STATUS 里,不记录在任何数据库元数据中,监控脚本通常漏掉它。只要看到 The table is full 且 tmpdir 和磁盘都充裕,第一反应就该去 ls -lh 看 ibtmp1。


















