
那是一个再平时不外的周三下昼,阳光透过落地窗在工位上投下斑驳的光影。我正慢悠悠地等放工——蓦的,手机“叮”地一声炸响,一条严重告警:“磁盘使用率超98%告警”。
一、【蹙迫告警】测试职业器磁盘使用率 98%!
系数办公室俄顷安逸了一秒,接着炸开了锅。
“不是上周才算帐过日记吗?奈何又满了?”
“是不是谁又跑了个全量导出?”
“快查查是不是有大文献!”
DBA共事七手八脚地登录职业器,脱手 du -sh * 扫描目次。我也偷偷 SSH 进了 MySQL 的数据目次,思望望有莫得杰出。
然后,我看到了它——192G的文献:

-rw-r----- 1 mysql mysql 192G Aug 12 16:20 ibtmp1
192GB!
一个名字平平无奇、却如黑洞般合并磁盘空间的文献——ibtmp1。
二、这个“鬼魂文献”到底是什么?
在 MySQL 5.7 及之后版块中,ibtmp1 是 InnoDB 引擎用于存储临时表的寂寥表空间文献。默出嫁置是:
innodb_temp_data_file_path = ibtmp1:12M:autoextend

真谛是:运行大小12MB,自动扩展,表面上不错无尽增长(只好磁盘还有空间),而问题就出在这“无尽”二字上。
而本次问题的缘由亦然因为测试环境没东说念主温暖性能问题(只温暖数据库是否可用),一朝有低效 SQL 庸俗创建临时表,ibtmp1 就会像吹气球雷同彭胀——直到撑爆系数磁盘。
三、怎样“驱魔”?三步解决
第一步:优雅停服,清空鬼魂
临时表空间只在 MySQL 运行时存在。只好重启实例,乐动手机app ibtmp1 就会自动清零。但为了数据安全,冷落先建树:
SET GLOBAL innodb_fast_shutdown = 0;
SHUTDOWN;
这样能确保 InnoDB 作念一次完好的 checkpoint,幸免不测。
注:MySQL 5.7+ 因循平直在 SQL 中本质 SHUTDOWN。
关机后,阿谁 192G 的“鬼魂”竟然灭绝了。
第二步:设上限,防复发
光清空不够,得治本。咱们在 my.cnf 中加上罢了:
innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:20G
当前,哪怕再有猖獗 SQL,最多也只可吃掉 20GB —— 超了就报错,开云体育(kaiyun)官方网站反而能露馅问题。
重启 MySQL 后考证:
SHOW VARIABLES LIKE 'innodb_temp_data_file_path';
-- 输出:ibtmp1:12M:autoextend:max:20G
第三步:揪出“真凶”——那些制造临时表的 SQL
为什么会有这样大临时表?得看哪些查询触发了 Using Temporary。
通过查询慢SQL,并检察本质运筹帷幄,咱们发现以下几种情况最容易“召唤鬼魂”:
1)GROUP BY 用到了无索引字段
EXPLAIN SELECT * FROM test_tmp1 GROUP BY col2;
-- Extra: Using temporary; Using filesort
2)GROUP BY 和 ORDER BY 字段不一致
即使齐有索引,也会用临时表:
EXPLAIN SELECT name FROM test_tmp1 GROUP BY name ORDER BY id DESC;
-- Extra: Using index for group-by; Using temporary; Using filesort
3)DISTINCT + ORDER BY 字段不匹配
EXPLAIN SELECT DISTINCT col2 FROM test_tmp1 ORDER BY name;
-- Extra: Using temporary; Using filesort
4)UNION(扫视:UNION ALL 已优化,不使用临时表)
EXPLAIN SELECT name FROM t1 UNION SELECT name FROM t1 WHERE id
-- 出现 UNION RESULT 行,Extra: Using temporary
5)INSERT INTO ... SELECT ...
尤其是大表自复制:
INSERT INTO test_tmp3 SELECT * FROM test_tmp3;
-- Extra: Using temporary
小结:
确切所灵验到临时表的场景,齐是慢查询的高危信号。
ibtmp1 暴涨,其实是数据库在向你求救:“快优化这些烂 SQL!”
四、模拟复现:亲目击证 ibtmp1 彭胀
1、模拟使用临时表空间的场景
为了考证,咱们作念了个小实验:
创建一张 1500 万行的大表 test_tmp3(无主键、无索引);
建树 tmp_table_size = 16M,ibtmp1:12M:autoextend:max:2G, 逼 MySQL 使用磁盘临时表;
本质 INSERT INTO test_tmp3 SELECT * FROM test_tmp3;
服从:
运行 ibtmp1:12MB
本质后:2.8GB
再本质一次(上限设为 2G):报错!
ERROR 1114 (HY000): The table '/tmp/#sql_xxx' is full
日记里也记了一笔:
[ERROR] The table '/tmp/#sql_xxx' is full
这恰是咱们思要的“熔断机制”——宁可让 SQL 失败,也不可让职业器宕机。
2、联系参数
除了 innodb_temp_data_file_path,还有几个参数会影响临时表活动:
tmp_table_size:内存临时表最大值
max_heap_table_size:用户界说 MEMORY 表的上限
default_tmp_storage_engine:临时表默许引擎(5.7+ 默许 InnoDB)
internal_tmp_disk_storage_engine:磁盘临时表引擎(8.0+ 引入)
它们互相影响,共同决定临时表是走内存还是磁盘。
五、尾声:鬼魂退散,系统壮盛
那天晚上,咱们不仅清掉了 192G 的“鬼魂”,还探本溯源干掉了三个低效查询。从此,测试环境再没因 ibtmp1 报警。而我也明显了一个兴味:数据库不会一头雾水变慢,也不会一头雾水吃光磁盘。它每一次“杰出”,齐是在用千里默的表情,讲演一个又一个被忽视的故事。
下次当你看到 ibtmp1 杰出彭胀,请别急着删文献——先问问:是谁,在背后写下了那行“可怕”的 SQL?
作家丨懂点IT的耿小厨开云体育
亚博体彩官方网站入口