Seconds_Behind_Master持续上涨但Exec_Master_Log_Pos几乎不动,大概率是主库存在未提交的大事务——该事务未COMMIT导致Binlog无法落盘和切换,从库IO线程无新日志可拉取,SQL线程被迫等待,虽显示正常运行实则“假性饿死”。

Seconds_Behind_Master 持续上涨,但 Exec_Master_Log_Pos 几乎不动,大概率是主库上有个大事务卡在“未提交”状态——不是它执行慢,而是它根本没提交,从库就一直等这个事务的 COMMIT event。
大事务未提交会阻塞 Binlog 切换
- MySQL 的 Binlog 是按事务粒度写入的,一个事务的所有变更(哪怕只有一条
UPDATE)必须等到COMMIT才会刷进当前 Binlog 文件,并生成对应的XID_LOG_EVENT - 如果事务长时间不提交(比如开发用客户端执行了
SELECT后忘了COMMIT,或应用层异常中断),Binlog 就卡在旧文件末尾,无法滚动到新文件 - 从库的 IO 线程只能拉取已落盘的 Binlog,而主库还没写完当前事务 →
Read_Master_Log_Pos停滞 → 从库“看起来没收到新日志”,实际是主库压根没发
从库 SQL 线程被假性“饿死”
- 即使主库已发出部分事件,只要事务没
COMMIT,从库 SQL 线程就必须串行等待,不能提前执行后续事务(保证 ACID 和复制一致性) - 这导致:
-
Slave_SQL_Running显示Yes,但Seconds_Behind_Master持续飙升 -
SHOW PROCESSLIST中 SQL 线程状态常为Waiting for dependent transaction to commit或Reading event from the relay log(实则无事可做) -
Relay_Log_Space不涨,说明中继日志几乎没新增内容
-
容易被忽略的“伪大事务”场景
- 不是只有
UPDATE t1 SET ... WHERE id BETWEEN 1 AND 1000000才算大事务 - 以下情况同样致命:
- 应用层开启事务后只执行一条
SELECT,然后连接空闲挂起(如 DBever、DBeaver 默认保持事务) - ORM 框架开启事务但未显式
commit或rollback(尤其在 try/catch 缺失时) - 存储过程中有异常分支遗漏
ROLLBACK,事务悬停
- 应用层开启事务后只执行一条
- 这类事务可能只改 0 行,但持有元数据锁 + 阻塞 Binlog 切换,危害比真正的大 DML 更隐蔽
查这类问题最直接的命令是:
SELECT trx_id, trx_state, TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS run_sec, trx_started, trx_query FROM information_schema.innodb_trx WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60 ORDER BY run_sec DESC;
重点看 trx_state = 'RUNNING' 且 run_sec 持续增长的记录——它们未必在执行,但一定没提交。
真正麻烦的不是“事务太大”,而是“事务忘了关”。一旦发生,从库同步就变成单点阻塞,所有后续变更全部排队,延迟秒数会指数级跳升。


















