临时表在基于语句的复制(SBR)下无法跨会话持久化,只在当前会话生命周期内存在;从库执行STOP SLAVE或意外重启后会话终止,临时表自动销毁,导致后续重放CREATE TEMPORARY TABLE等语句时因表不存在而报错1146或1032;必须确保Slave_open_temp_tables为0后才能安全停止或重启;ROW格式虽可避免报错但使临时表数据不同步,真正安全做法是避免在复制链路中使用临时表。

临时表在基于语句的复制(SBR)下无法跨会话持久化
临时表只在当前会话生命周期内存在,从库执行 STOP SLAVE 或意外重启后,会话终止,临时表自动销毁。而基于语句的复制(binlog_format = STATEMENT)会原样重放主库执行过的 SQL,比如 CREATE TEMPORARY TABLE t1 AS SELECT ...,但该语句在从库执行时,依赖的临时表可能已不存在,或被其他会话覆盖,导致后续 INSERT INTO ... SELECT FROM t1 报错 Error 1146: Table 't1' doesn't exist 或 Error 1032: Can't find record。
STOP SLAVE 后未清空临时表就重启,SQL 线程直接失败
这是最典型的中断场景。从库执行 STOP SLAVE 并未自动清理临时表;若此时重启 mysqld,所有临时表丢失,但中继日志(relay log)里还存着对这些临时表的操作。SQL 线程启动后尝试执行,必然失败。
- 必须先确认无活跃临时表:
SHOW STATUS LIKE 'Slave_open_temp_tables';—— 返回值必须为0 - 若不为 0,不能直接关库,应先
STOP SLAVE SQL_THREAD;,等待Slave_open_temp_tables归零,再STOP SLAVE IO_THREAD; - 严禁在
Slave_open_temp_tables > 0时执行RESET SLAVE或重启进程
ROW 格式能绕过问题,但不是万能解
binlog_format = ROW 下,临时表本身不写入 binlog,所有变更都以行事件形式记录,因此不会出现“找不到临时表”的错误。但这带来新风险:
- 临时表数据不会同步,主从该表内容天然不一致 —— 如果业务逻辑依赖临时表结果做后续判断,从库可能出错
- 如果主库用临时表做中间计算(如
INSERT INTO real_table SELECT * FROM tmp),从库虽能执行成功,但中间状态不可见、不可审计 - 某些 DDL 操作(如
ALTER TEMPORARY TABLE)在 ROW 模式下仍可能被忽略或报错,取决于 MySQL 版本
真正安全的做法是避免在复制链路中用临时表
临时表本质是会话级缓存工具,不适合参与主从数据流。生产环境应主动规避:
- 用普通表 + 唯一前缀/时间戳命名替代,例如
tmp_user_calc_20260904_123456,事后DROP - 改用 CTE(MySQL 8.0+)替代简单临时表场景,CTE 不落盘、无生命周期问题
- 若必须用临时表,确保它只出现在从库只读会话中(即不走复制线程),且不被任何复制事务引用
临时表引发的中断往往不报明显错误码,而是静默跳过或卡在某条语句上——查 Last_SQL_Error 之前,先看 Slave_open_temp_tables 和 Relay_Log_Space 是否异常增长,比盲目跳过更可靠。


















