mysql报got error 28本质是操作系统enospc错误,即tmpdir所在分区(可能为/var/tmp、/run/mysqld或容器小volume)空间或inode耗尽;须先查show variables like 'tmpdir',再df -h确认对应挂载点使用率,针对性清理残留临时文件并优化sql。

这个错误不是 MySQL 崩了,是操作系统说“没地方写了”——ENOSPC,即磁盘或临时分区满载。关键不在数据库本身,而在它写临时文件的路径卡死了。
查清 MySQL 真正用的 tmpdir 路径
别猜 /tmp,MySQL 的 tmpdir 可能被设成 /var/tmp、/run/mysqld,甚至容器里一个 1GB 的小 volume。不确认就清理,大概率白忙。
- 运行
mysql -e "SHOW VARIABLES LIKE 'tmpdir';"拿到真实路径 - 立刻执行
df -h $(mysql -Nse "SELECT @@tmpdir"),看这个路径挂载点是否 100% 满 - 特别注意:
/tmp是tmpfs(内存文件系统)时,df -h /tmp显示已用 100%,但free -h可能看不出——它吃的是内存,不是磁盘
清理残留临时文件要带条件,不能直接 rm -rf /tmp/*
MySQL 异常退出后,#sql_*.MYD、#sql_*.{frm,ibd} 这类临时表文件可能还占着空间,但 ls 看不见(已被删除但句柄未释放)。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 先查占用:运行
lsof +L1(Linux)或lsof | grep deleted,找标记为deleted的大文件 - 确认无活跃 MySQL 进程在用,再清理:例如
find $(mysql -Nse "SELECT @@tmpdir") -name "#sql_*" -mmin +60 -delete(只删 1 小时前的) - 绝对不要
rm -rf /tmp/*:可能误删mysql.sock、systemd-private-*等关键临时文件,导致服务起不来 -
ibtmp1是 InnoDB 全局临时表空间,不能手动删;必须重启 MySQL 才重建(前提是配置了innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:2G)
临时救急:让当前查询走内存,而不是落盘
调大内存参数不能解决根本问题,但能让单次查询绕过磁盘临时表,快速恢复业务。
- 会话级生效(适合调试或短连接应用加在 query 前):
SET SESSION tmp_table_size = 268435456;SET SESSION max_heap_table_size = 268435456;
注意:两个值必须相等,否则以小者为准 -
sort_buffer_size和read_rnd_buffer_size是 per-connection 参数,设太高会撑爆内存;建议单个连接不超过 2M - 这些设置重启后失效;若要持久化,改
my.cnf并重启 MySQL
永久修复必须改配置,且 tmpdir 不可动态修改
SET GLOBAL tmpdir = '/new/path' 是无效操作——该变量不可动态修改。必须停服务、改配置、重启。
- 新路径不能是 NFS、overlayfs 或 tmpfs;推荐
ext4或xfs分区,例如/mnt/mysql-tmp - 确保目录存在、属主为
mysql:mysql、权限为750,且空间充足(建议预留 ≥20GB) - 在
my.cnf的[mysqld]段落显式写:tmpdir = /mnt/mysql-tmp - 重启后验证:
SHOW VARIABLES LIKE 'tmpdir';+ls -ld /mnt/mysql-tmp
真正容易被忽略的是:error 28 往往是 SQL 本身有问题的信号。比如没索引的 GROUP BY、大偏移 LIMIT、SELECT * 配合 ORDER BY——这些都会强制生成巨型临时表。调参只是缓冲,索引优化和 SQL 改写才是根治点。










