主库 binlog dump 线程在从库执行 START SLAVE 后,由从库 IO 线程发起 COM_BINLOG_DUMP 请求时按需创建,随连接建立而启动、断开而退出,非常驻进程。

主库 binlog dump 线程是怎么被触发的?
从库执行 START SLAVE 后,才会真正激活主库上的 binlog dump 线程——它不是常驻进程,而是按需创建、随连接生命周期存在。只要从库 IO 线程连上来、发起请求,主库就新建一个 dump 线程专门服务它;从库断开或执行 STOP SLAVE,该线程立刻退出。
常见错误现象:SHOW PROCESSLIST 在主库看不到 Binlog Dump 线程,但从库显示 Slave_IO_Running: Yes——这说明连接已建立,但 dump 线程可能刚启动又因网络抖动 / 认证失败快速退出,建议立刻查主库错误日志(/var/log/mysqld.log)里有没有 Access denied 或 Failed to authenticate。
- dump 线程只读 binlog 文件,不写、不修改,但它会在读取每个 event 时对 binlog 文件加短暂共享锁(
read lock),读完即放,不影响主库写入 - 主库有 N 个从库连接,就有 N 个 dump 线程,每个线程独立维护自己的读取位置(
File+Position),互不干扰 - 如果主库启用了
expire_logs_days,而某个从库长期断连未拉取,dump 线程尝试读已被清理的 binlog 时会报错Could not find first log file name in binary log index file,此时必须重做同步
从库 IO 线程如何发起并维持长连接?
IO 线程本质是个「带心跳的 TCP 客户端」:它用配置的 master_host、master_port、账号密码连主库,成功后发送一个 COM_BINLOG_DUMP 协议包,里面明确带上要从哪个 File 和 Position 开始拉取——这个位置来自 CHANGE MASTER TO 时指定的值,或 GTID 模式下的 master_auto_position=1。
使用场景:跨公网同步时,IO 线程频繁重连,不是因为“连不上”,而是因为中间防火墙 / 云厂商 LB 的空闲超时(如 60s)主动断开了 TCP 连接。IO 线程检测到断连后会立即重试,但每次重试都重新握手、认证、定位,加重主库负担。
- 可通过调大主从两端的
net_read_timeout和net_write_timeout(建议 ≥ 60)减少误断 - MySQL 5.7+ 支持
MASTER_HEARTBEAT_PERIOD(单位毫秒),例如设为15000,让 IO 线程每 15 秒发一次心跳包,保活连接 - IO 线程写 relay log 是顺序追加、fsync 写盘(受
sync_relay_log=1控制),所以即使从库 crash,只要 relay log 没丢,重启后能从断点继续,不丢数据
为什么 dump 和 IO 线程之间是「拉模式」而非「推模式」?
因为 MySQL 复制协议设计上把「节流权」交给从库:IO 线程可以控制拉取速度、暂停、跳过某些事件(比如过滤库表),而 dump 线程只是被动响应请求,不主动推送。这种解耦让从库能自主应对延迟、磁盘满、SQL 执行慢等问题。
性能影响:当从库 SQL 线程严重滞后(Seconds_Behind_Master 很大),IO 线程仍在高速拉取 binlog 并写入 relay log,可能导致 relay-log.index 文件暴增、磁盘写满;此时不能只停 SQL 线程,必须同时 STOP SLAVE IO_THREAD,否则 relay log 仍会无限增长。
- IO 线程拉取的是原始 binlog event 流,不解析、不校验,所以 relay log 和主库 binlog 内容完全一致(除格式封装外)
- GTID 模式下,IO 线程请求时不再传 Position,而是传已执行的 GTID set,dump 线程据此计算出缺失的事务并返回,避免位点错乱
- 若主库 binlog 格式为
MIXED或ROW,dump 线程发送的 event 包含完整行变更,IO 线程照单全收;但若为STATEMENT,某些非确定性语句(如SYSDATE()、UUID())在从库重放时可能产生不同结果
最容易被忽略的协议细节:连接身份与权限绑定
dump 线程运行在主库用户上下文中,但它用的不是你 CHANGE MASTER TO 里填的账号,而是从库 IO 线程连接时提供的认证凭据——也就是说,主库上必须显式创建该账号,并赋予 REPLICATION SLAVE 权限,否则 dump 线程一启动就报错退出,且错误只记在主库日志里,从库 SHOW SLAVE STATUS 中 Seconds_Behind_Master 可能一直为 NULL,IO_Running 显示 Connecting 却卡住不动。
- 账号必须限定来源 IP(如
'repl'@'192.168.1.100'),不能用'repl'@'%'配合弱密码,否则 dump 线程可能被未授权客户端冒用 - MySQL 8.0 默认认证插件是
caching_sha2_password,而老版本从库(如 5.7)不支持,会导致 IO 线程连接失败,需在主库创建用户时显式指定IDENTIFIED WITH mysql_native_password - dump 线程的连接状态在主库
SHOW PROCESSLIST中显示为User: system user,Host 为空,不要误以为它是系统内部线程——它就是你那个从库连上来的会话,只是用户名被隐藏了
复制协议本身很简单,但 dump 和 IO 线程之间的每一次 handshake、每一个 position 对齐、每一次超时重试,都依赖底层 TCP 稳定性和权限 / 配置的精确匹配。线上出问题时,别急着怀疑 binlog 损坏,先盯住两边的连接状态和错误日志,90% 的「同步卡住」其实发生在第一步握手阶段。