“The table is full”真因多为内存临时表超限,而非磁盘空间不足;核心是tmp_table_size或max_heap_table_size过小导致频繁落盘,或tmpdir所在分区inode耗尽、配额限制、ibtmp1不可扩展所致。

MySQL报错“The table is full”真因不是磁盘满,而是内存临时表超限
这个错误90%以上跟磁盘剩余空间无关,真正触发点是tmp_table_size或max_heap_table_size限制被突破,导致MySQL被迫把内存临时表转存到磁盘——而此时若tmpdir所在分区的ibtmp1或系统临时目录(如/tmp)已无足够连续空间,就抛出该错误。注意:即使磁盘还有几十GB空闲,只要临时文件无法扩展(比如inode耗尽、配额限制、或ibtmp1被设为固定大小且已满),照样报错。
快速定位是内存限制还是磁盘问题
先查当前会话实际用到的临时表类型和大小:
SHOW STATUS LIKE 'Created_tmp%';
Created_tmp_tables表示在内存中创建的临时表数量;Created_tmp_disk_tables表示已落地到磁盘的临时表数量。如果后者占比高(比如超过20%),说明频繁触发落盘,大概率是tmp_table_size太小。
再确认关键参数值:
SELECT @@tmp_table_size, @@max_heap_table_size, @@tmpdir;
检查@@tmpdir路径的实际可用空间和inode:
-
df -h <tmpdir路径>—— 看剩余容量 -
df -i <tmpdir路径>—— 看inode是否耗尽(常见于大量小临时文件) - 若
@@tmpdir指向/tmp,还要确认是否挂载了noexec或nosuid选项(可能阻止MySQL写入)
调整tmp_table_size和max_heap_table_size要同步且合理
这两个参数必须保持一致,否则以较小值为准。例如只调大tmp_table_size但max_heap_table_size仍很小,临时表还是会很快落盘。
修改建议(需重启或动态生效):
- 线上环境建议从
64M起步(SET GLOBAL tmp_table_size = 67108864;),再观察Created_tmp_disk_tables是否下降 - 不要盲目设到几GB——过大的值会导致单个查询占用过多内存,可能引发OOM Killer杀进程
- 若使用Percona Server或MySQL 8.0+,可启用
internal_tmp_mem_storage_engine=MEMORY并配合temptable_max_ram更精细控制 - 确认
my.cnf中两参数都显式配置,避免依赖隐式默认值
tmpdir路径本身有坑:别用/tmp,优先指向SSD独立分区
/tmp常被清理工具(如systemd-tmpfiles)定期清空,或受noexec限制;MySQL 5.7+默认用ibtmp1存内部临时表,但它不自动扩展(除非设innodb_temp_data_file_path=ibtmp1:12M:autoextend)。
稳妥做法:
- 新建专用目录:
mkdir -p /data/mysqltmp && chown mysql:mysql /data/mysqltmp - 在
my.cnf中设置:tmpdir = /data/mysqltmp - 确保该目录所在分区是SSD且预留≥20%空间,避免和
datadir混用同一慢速磁盘 - 重启MySQL后验证:
SELECT @@tmpdir;和ls -l /data/mysqltmp确认MySQL进程有写权限
临时表落盘性能敏感,路径选错比参数调小更难排查。很多团队卡在这里两周,其实只是tmpdir指向了一个满配额的NFS共享目录。


















