如何排查MySQL主从复制导致的临时文件溢出问题?

作者:袖梨 2026-08-08

答案是主从复制中SQL线程在从库执行DDL或引用临时表时,因tmp_table_size与max_heap_table_size不等或ibtmp1空间耗尽,导致临时表被迫落盘并报“The table is full”或“Incorrect key file”错误。

主从复制本身不直接生成临时文件,但复制过程中的DDL操作、SQL线程执行、临时表同步等行为会触发临时空间暴涨——问题通常出在从库,且常被误判为“主库写多”,实际是SQL线程在从库本地执行时撑爆ibtmp1/tmp

看Last_SQL_Error是否含Incorrect key file for table或The table is full

这是最直接的信号。一旦show slave statusG中出现:

  1. Last_SQL_Errno: 1034 + Last_SQL_Error: Error 'Incorrect key file for table ...' → 基本锁定为临时表落盘失败
  2. Last_SQL_Error里带The table is full → 不一定是磁盘满,更可能是内存临时表阈值被卡死,被迫写入磁盘临时空间
  3. 注意:该错误一定出现在SQL线程(即Slave_SQL_Running: No),和IO线程无关

查Created_tmp_disk_tables是否突增

临时文件溢出不是偶发事件,而是持续性压力积累。用状态变量确认趋势:

  1. 执行SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';,记录每秒增量;若稳定 >50次/秒,说明大量查询被迫落盘
  2. 对比Created_tmp_tables,算比值:Created_tmp_disk_tables / Created_tmp_tables > 0.1即属异常
  3. 重点观察时间点:是否和某次ALTER TABLECREATE TABLE ... SELECT或大批次INSERT ... SELECT同步发生?这类DDL/DML在从库回放时会重建临时结构

确认tmpdir和ibtmp1真实占用位置

别只看df -h根分区——MySQL可能把临时文件写到了意想不到的地方:

  1. 查实际路径:SELECT @@tmpdir;,常见值有/tmp/var/tmp/data/mysql/tmp,对应挂载点要单独df -h
  2. 查InnoDB临时表空间:SELECT @@innodb_temp_data_file_path;,默认是ibtmp1:12M:autoextend,它会无限增长直到磁盘满
  3. lsof +D /path/to/tmpdir确认是不是mysqld进程在往里面狂写(注意:重启前ibtmp1不会缩容,即使删了临时表)

改参数前先做三件事:停SQL线程、清空临时表、验证tmp_table_size与max_heap_table_size是否相等

盲目调参可能让问题更隐蔽:

  1. 先停SQL线程:STOP SLAVE SQL_THREAD;,避免新临时表持续生成
  2. 手动清理:DROP TEMPORARY TABLE IF EXISTS(如有显式创建)、KILL掉长时间Creating sort indexCopying to tmp table状态的连接
  3. 必须验证:SELECT @@tmp_table_size, @@max_heap_table_size; —— 两个值单位是字节,必须完全一致;若不等,MySQL永远按小的那个截断
  4. 配置文件中必须并列写两行:tmp_table_size = 268435456max_heap_table_size = 268435456(即256MB),不能只改一个

真正棘手的点在于:DDL操作(比如ADD COLUMN)在从库回放时,即使主库没报错,从库也可能因ibtmp1已占上百GB而无法分配新段——此时RESET SLAVE无用,STOP SLAVE也救不了,唯一解是重启MySQL释放ibtmp1。但重启前得确保没有长事务卡住binlog位置,否则主从数据会断层。

相关文章

精彩推荐