从库阻塞复制的典型表现是SHOW PROCESSLIST中大量Waiting for table metadata lock或global read lock,且Seconds_Behind_Master持续上涨但Slave_SQL_Running为Yes;根本原因是长查询或未提交事务锁住DDL或大事务回放所需元数据。

从库查询阻塞复制的典型表现
你执行 SHOW PROCESSLIST 时看到大量 Waiting for table metadata lock 或 Waiting for global read lock,同时 SHOW SLAVE STATUS\G 中 Seconds_Behind_Master 持续上涨,但 Slave_SQL_Running 是 Yes——这大概率不是主从网络或磁盘问题,而是从库上长查询/未提交事务锁住了 DDL 或大事务回放所需的元数据。
为什么调整 transaction_isolation 能缓解?
MySQL 从库默认用 REPEATABLE-READ 隔离级别,它会为所有读操作加一致性读视图(MVCC),而大事务或长时间运行的 SELECT 会拖住 purge 线程,导致 undo log 无法清理,进而卡住后续需要清理旧版本的 SQL 线程(尤其是含 UPDATE/DELETE 的事件)。改成 READ-COMMITTED 后,每次语句只读取语句开始时的快照,不维护整个事务级视图,undo 回收更及时。
无序列表:
-
READ-COMMITTED下,SELECT不阻塞INSERT/UPDATE/DELETE回放,反之亦然;REPEATABLE-READ下,一个长SELECT可能让 SQL 线程等它释放 read view - 仅对从库生效:主库隔离级别不影响复制,但建议主从保持一致,避免应用误依赖隔离行为
- 注意 binlog 格式:若用
STATEMENT,READ-COMMITTED对某些函数(如NOW())行为有影响;ROW格式下基本无副作用
怎么安全地改从库隔离级别
不能直接改全局变量——那会影响所有新连接,包括可能正在跑的监控或运维脚本。必须精准控制作用域。
无序列表:
- 临时生效(重启失效):
SET GLOBAL transaction_isolation = 'READ-COMMITTED';,但需确保从库没有活跃的长事务(查SELECT * FROM information_schema.INNODB_TRX) - 持久生效:在从库配置文件中加
transaction_isolation = READ-COMMITTED,然后mysqladmin shutdown && mysqld_safe重启(不要用SERVICE mysql restart,避免跳过配置重载) - 验证是否生效:
SELECT @@global.transaction_isolation, @@session.transaction_isolation;,两个都应返回READ-COMMITTED - 别漏掉已存在的连接:老连接仍用旧隔离级别,需等它们自然退出或主动 kill(
KILL CONNECTION xxx)
比改隔离级别更关键的三件事
调隔离级别只是止痛药。真正压垮从库的,往往是没被发现的慢查询、没设超时的监控采集、或者应用连错从库执行了写操作。
无序列表:
- 检查
long_query_time是否太松(比如设成 10 秒),从库建议调到 1–2 秒,并开启log_queries_not_using_indexes - 确认所有业务读请求是否真的走从库——有些 SDK 默认读主库,但配置里写了从库地址,结果连上去却执行了
INSERT,触发 MDL 锁冲突 - SQL 线程卡住时,先看
SHOW ENGINE INNODB STATUS\G的LATEST DETECTED DEADLOCK和TRANSACTIONS部分,而不是急着调参数
隔离级别调完不等于万事大吉,真正麻烦的是那些没进 slow log、但持续占着 read view 的“安静型”查询——它们不会报错,只会悄悄拖慢复制。










