ERROR 1205在从库出现本质是SQL线程执行relay log时锁等待超时,主库不报因并发低、事务短;根本原因是索引缺失、长事务或非同步写入导致锁阻塞,需优先检查read_only状态、添加缺失索引并规范主库写法。

主从同步本身不会触发 ERROR 1205(Lock wait timeout exceeded)——这个错误只发生在从库的 SQL 线程执行 relay log 中的 DML 时,本质是「从库写入卡住了」,和主从复制机制无关。真正要解决的,是那个在从库上死等行锁、最终超时的 UPDATE/DELETE 语句。
为什么从库会报 1205,而主库不报?
主库写入时可能很快拿到锁(并发低、事务短),但从库 SQL 线程是单线程(默认)串行回放,一旦前面某条语句持锁时间长(比如大事务未提交、慢查询、索引缺失),后面的语句就会排队等待;等超过 innodb_lock_wait_timeout 就直接报 ERROR 1205。常见诱因包括:
- 主库发来一条
UPDATE user SET status=1 WHERE name='xxx',但从库该表没给name加索引 → 全表扫描 + 行锁升级为表锁 → 后续所有涉及该表的语句全被堵住 - 主库有长事务(如导数据脚本),从库回放时恰好撞上同一行的其他更新
- 从库开启了
read_only=OFF,或被误操作手动写了数据,导致主从数据不一致、索引失效、锁范围异常扩大
查当前卡住的从库事务:别只看 processlist
SHOW FULL PROCESSLIST 只能看到 SQL 线程状态是 Reading event from the relay log,看不出它到底卡在哪条 SQL。真要定位,得结合:
-
SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED ASC—— 找出最早开始却还没结束的事务,重点看TRX_QUERY和TRX_WAIT_STARTED -
SELECT * FROM performance_schema.data_lock_waits(MySQL 8.0+)—— 直接看到谁在等谁的锁,BLOCKING_ENGINE_TRANSACTION_ID对应持锁事务 -
SHOW ENGINE INNODB STATUS\G—— 拉到最后的LATEST DETECTED DEADLOCK段,即使不是死锁,也常含最近一次锁等待上下文
调 innodb_lock_wait_timeout 是双刃剑
设大了(比如 SET GLOBAL innodb_lock_wait_timeout = 300)能暂时让从库“多等一会儿”,但掩盖问题:用户请求可能卡 5 分钟才失败,监控毛刺不明显,故障更难暴露。设小了(如 5 秒)又容易把正常争抢判成失败,尤其在批量回放初期。更关键的是:
- 它只对新连接生效,已卡住的 SQL 线程不受影响(必须
STOP SLAVE; START SLAVE;才重连) - 不解决锁源——比如缺失索引导致的表级锁,调 timeout 毫无意义
- 从库若长期依赖调高 timeout,说明主库写法或从库配置有硬伤,迟早崩
真正该做的三件事
比起调参数,优先做这些:
- 确认从库是否真
read_only=ON(SELECT @@read_only),避免混入非同步写入破坏一致性 - 检查报错语句涉及的表,用
EXPLAIN FORMAT=TREE跑一遍对应 SQL,看是否走了索引;没走就加,别拖 - 主库侧收敛写法:避免
UPDATE ... WHERE不带确定性索引条件;拆大事务;更新固定顺序(如总是按id ASC批量更新)
锁等待超时从来不是孤立错误,它是数据库在喊:“这行/这张表现在太热了,你得管管访问方式。”


















