最可靠方式是抓取主库到从库的tcp流量,如用tcpdump或iftop;binlog磁盘体积不等于复制带宽,因存在过滤、压缩、重传等差异;带宽异常升高往往反映复制链路问题而非业务增长。

怎么看主从复制实际用了多少带宽
MySQL 主从复制本身不直接暴露“每秒传输多少 KB”的指标,SHOW SLAVE STATUS 里只有 Seconds_Behind_Master 和 IO/SQL 线程状态,没法换算成带宽。真实带宽消耗得从网络层反推——不是看 MySQL,是看它用的 TCP 连接。
最可靠的方式是抓取主库上发往从库 IP:port 的流量。比如主库 IP 是 10.0.1.10,从库连的是 3306,那就盯这个连接:
sudo tcpdump -i any -w replication.pcap host 10.0.1.10 and port 3306 and dst 10.0.1.20
注意:dst 10.0.1.20 要换成你从库的真实 IP;如果主从走的是非标端口(比如 3307),记得改端口号。
- 别在生产高峰长期跑
tcpdump,文件增长快,磁盘和 CPU 都吃紧 - Linux 上可用
iftop -P 3306 -f "host 10.0.1.20"快速看实时速率,更轻量 - 云环境(如阿里云 ECS)可直接看「云监控」里的「外网/内网出方向流量」,筛选源 IP + 目标 IP 即可
binlog 文件大小 ≠ 复制带宽消耗
有人用 du -sh /var/lib/mysql/mysql-bin.* 算日志体积,再除以时间,当成带宽——这会严重高估。因为 binlog 是全量写入磁盘的,但复制只传其中一部分:比如 GTID 过滤、replicate-do-db 设置会让从库跳过某些库;主库上大量 INSERT ... SELECT 或大事务产生的临时日志,在复制时可能被压缩或合并;还有半同步开启时重传、网络丢包重发,这些都让“发送字节数”和“binlog 文件体积”不一致。
-
SHOW BINARY LOGS显示的是磁盘占用,不是网络发出量 - 如果开了
binlog_row_image=MINIMAL,UPDATE 只传变化列,比 FULL 模式省一半以上带宽 - 主库
max_allowed_packet设太小会导致大事务被拆成多个包,增加 TCP 包头开销,反而推高带宽
从库拉取慢导致带宽“脉冲式”堆积
当从库 SQL 线程卡住(比如遇到锁等待、大 DDL、磁盘 I/O 延迟),IO 线程仍持续从主库读 binlog 并缓存在 relay_log 里。这时主库出口带宽不会降,反而可能升高——因为从库会不断重连、重请求缺失事件,甚至触发 CHANGE MASTER TO ... RELAY_LOG_FILE 手动跳位点,引发重复拉取。
查这个现象的关键指标是:
- 主库
SHOW PROCESSLIST里有没有多个Binlog Dump线程连同一个从库(说明频繁断连重连) - 从库
Seconds_Behind_Master持续上涨,同时Relay_Log_Space不断增大 - 主库
netstat -an | grep :3306 | grep ESTABLISHED | wc -l突然变多
这时候带宽峰值未必反映业务压力,而是复制链路健康度告警。
想长期监控,别自己解析 tcpdump
手动抓包只能应急。真要长期看,优先用系统级工具聚合统计,而不是进 MySQL 解析 binlog:
- 用
ss -i查单个连接的rcv_ssthresh/cwnd,能看出 TCP 拥塞情况(间接影响有效带宽) - Prometheus +
mysqld_exporter只能报mysql_slave_status_seconds_behind_master,不提供带宽,得配node_exporter的node_network_transmit_bytes_total{device="eth0", instance="master-ip"},再加 label 过滤目标从库 IP - 如果主从走专线或 VPC 内网,交换机镜像端口 +
ntopng是最准的,但运维成本高
真正难的从来不是“怎么拿到数字”,而是区分清楚:这个带宽是业务写入驱动的,还是复制机制缺陷导致的无效重传——后者修好了,带宽自然下来,不用扩容网络。










