开云体育 MySQL里藏着一个会我方长大的文献, 90%的DBA齐忽略了

 94    |      2026-03-30 21:03

开云体育 MySQL里藏着一个会我方长大的文献, 90%的DBA齐忽略了

那是一个再平时不外的周三下昼,阳光透过落地窗在工位上投下斑驳的光影。我正慢悠悠地等放工——蓦的,手机“叮”地一声炸响,一条严重告警:“磁盘使用率超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的耿小厨开云体育

亚博体彩官方网站入口