myisam表锁导致从库sql线程完全阻塞:因不支持行级锁,写操作触发整表锁,单线程回放binlog时后续事务彻底卡死,表现为seconds_behind_master上涨、relay_log_pos停滞、sql线程状态为locked或waiting for table flush,且并行复制失效。

MyISAM表锁导致SQL线程完全阻塞
MyISAM不支持行级锁,任何写操作(INSERT、UPDATE、DELETE)都会触发整表锁。从库的SQL Thread是单线程串行回放binlog的,一旦遇到一个MyISAM表被锁住,后续所有事务都会排队等待——不是变慢,而是彻底卡死。
典型现象包括:Seconds_Behind_Master持续上涨、Relay_Log_Pos停滞不动、SHOW PROCESSLIST中SQL线程状态为Locked或Waiting for table flush、SHOW OPEN TABLES WHERE In_use > 0显示某MyISAM表长期In_use = 1。
主库备份语句会直接传导到从库锁表
像mysqldump --lock-all-tables这类工具在主库执行时,会在binlog里记录一条FLUSH TABLES WITH READ LOCK语句。从库照单全收,立刻对所有MyISAM表加全局读锁,连带阻塞后续所有DML回放。
即使主库只执行了1秒的锁表操作,从库SQL线程可能被堵住几分钟甚至更久,因为:
- 锁表期间产生的binlog无法应用
- 解锁后还需逐条重放积压的relay log
- 并发插入(concurrent_insert)在从库无效,回放必须严格按顺序
残留系统表仍是隐性雷区
MySQL 5.6及更早版本中,mysql.proc、mysql.event等系统表默认使用MyISAM引擎。即便业务表已全量迁移到InnoDB,这些表仍可能被CREATE PROCEDURE或定时事件触发写入,进而引发锁表延迟。
检查命令:SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE ENGINE = 'MyISAM' AND TABLE_SCHEMA NOT IN ('information_schema', 'performance_schema', 'sys');
迁移时务必注意:
- 对业务表执行ALTER TABLE db.tbl ENGINE = InnoDB前,先设SET sql_log_bin = 0,避免写入binlog造成循环
- 系统表不能直接ALTER,必须升级MySQL至5.7+或手动重建
并行复制对MyISAM完全失效
MySQL 5.7+的slave_parallel_type = LOGICAL_CLOCK依赖事务间无锁冲突的前提。而MyISAM表任意写操作都产生全表锁,导致所有涉及同一MyISAM表的事务被迫串行,slave_parallel_workers再高也起不到加速作用。
这意味着:
- 即使开了16个并行工作线程,只要有一张MyISAM表频繁更新,实际还是单线程干活
- slave_preserve_commit_order = 1等优化参数在此场景下形同虚设
- 延迟排查时容易误判为“SQL线程性能不足”,实则根源是引擎选型错误
真正棘手的点不在迁移操作本身,而在于MyISAM锁行为在从库上被放大了——主库的短时锁,在从库变成不可预测的长时阻塞;且这种阻塞不报错、不中断复制,只是安静地拖垮Seconds_Behind_Master。只要还有任意一张MyISAM表存在,就随时可能成为延迟爆发的导火索。











