Ubuntu 20.04 上 MySQL 8.0,4 核 8G,tmpdir 还是默认的 /tmp,跑一张统计报表时报 Error writing file ‘/tmp/MYb3f2’ (Errcode: 28 – No space left on device),同一时刻 df 显示根分区已经满。
一开始怀疑是「查询里带了 text 或者 blob 字段,内存临时表存不下,直接走磁盘临时表」,查了一圈,方向不对。
把日志和配置对完,能解释这个现象的基本就这几处。group by 的字段没有索引,优化器只能建内部临时表来做分组。另一种情况是tmp_table_size 与 max_heap_table_size 取的是较小值,超过就落到磁盘上。
不容易想到的是,tmpdir 和数据目录在同一块盘,临时文件把数据盘剩余空间一起吃光。
动手时先看落盘临时表的增速
mysql -e 'show global status like "Created_tmp_disk_tables"; show global status like "Created_tmp_tables";'
然后把临时目录挪到数据盘并给足权限
mkdir -p /data/mysqltmp && chown mysql:mysql /data/mysqltmp && mysql -e 'set global tmpdir="/data/mysqltmp";'
随后把内存临时表上限一起调大
mysql -e 'set global tmp_table_size=268435456; set global max_heap_table_size=268435456;'
等前面都确认过,再找到真正落盘的那条语句并补索引
mysql -e 'select digest_text,sum_created_tmp_disk_tables from performance_schema.events_statements_summary_by_digest order by sum_created_tmp_disk_tables desc limit 5\G'
改完先别撤,确认这几项。Created_tmp_disk_tables 的增速回落到个位数每分钟,df 显示根分区与数据盘空间稳定,报表脚本不再报 Errcode 28。
补一句。tmpdir 用 set global 改只在当前实例有效,配置文件里也要写,否则下次重启又回到根分区。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
