seconds_behind_master仅反映sql线程最后回放事件的时间戳与从库当前时间差,不体现io线程滞后、relay log堆积、大事务执行中时间戳停滞、主从时钟不同步及并行复制下worker实际进度等关键延迟因素。

用 mysql 命令连上从库查 Seconds_Behind_Master 最直接
主从延迟本质就是从库 SQL 线程落后主库多少秒,MySQL 把这个值存在 SHOW SLAVE STATUS 的 Seconds_Behind_Master 字段里。不用装额外组件,只要能 SSH 到从库、且该库的 MySQL 客户端可访问(本地或远程),一条命令就能取到:
mysql -u admin -p'xxx' -e "SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master:" | awk '{print $2}'
注意几个实操细节:
-
mysql命令必须在目标从库所在机器上执行(或配置好远程访问权限),不能只靠 SSH 转发端口后在跳板机上查——因为SHOW SLAVE STATUS只对本机 MySQL 实例有效 - 如果输出是
NULL,说明复制已断(Slave_IO_Running: No或Slave_SQL_Running: No),脚本里得单独判断,不能只看数字 - 某些 MySQL 8.0+ 版本在无复制时该字段可能显示
NULL或空,建议加|| echo 0防止管道中断
用 ssh 批量拉取多台从库延迟值要控制并发和超时
把上面那条命令封装进 for 循环不难,但真跑十几台时容易卡死或漏结果。关键不是“怎么循环”,而是“怎么稳住”:
- 每台机器用独立
ssh连接,别用ssh -f后台丢包;加-o ConnectTimeout=5 -o BatchMode=yes避免交互卡住 - 延迟值采集本身要设超时:
timeout 8s mysql -u... -e "SHOW SLAVE STATUS\G",防止 MySQL 锁死或网络抖动拖垮整个脚本 - 别用
echo "$host: $(ssh ...)"这种写法——一旦某台失败,整行输出就乱;改用临时文件或数组缓存结果,失败时记录$host: ERROR - 如果从库分布在不同内网段,考虑用跳板机中转,但
ProxyCommand要配在~/.ssh/config里,别硬编码在脚本里
把延迟数据推到 curl + Prometheus Pushgateway 是轻量实时追踪的关键
单纯写日志或打印到终端没用,得让监控系统能抓取。Pushgateway 是最省事的选择,不用改现有 Prometheus 架构:
- 每台从库的延迟值按指标格式构造:
mysql_slave_delay_seconds{instance="db-prod-01"} 42 - 用
curl -X POST --data-binary @- http://pushgw.example.com/metrics/job/mysql_slave_delay推送,注意job=名称要统一,否则会被当新 job 清掉 - 推送前先清旧数据:
curl -X DELETE http://pushgw.example.com/metrics/job/mysql_slave_delay/instance/db-prod-01,不然历史异常值会残留 - 别用
sleep 60做轮询——Pushgateway 不是时间序列数据库,高频推送会撑爆内存;建议间隔 ≥30 秒,且用at或systemd timer控制节奏
遇到 Access denied for user 或 Can't connect to local MySQL server 别急着改权限
这两个错误占实际部署问题的 70% 以上,但多数不是权限配置错,而是路径和上下文不对:
-
Can't connect to local MySQL server:脚本里写的mysql是调用了/usr/bin/mysql,但有些机器(如 CentOS Stream)默认没装客户端包,得先yum install mysql,不是mysql-server -
Access denied:检查mysql -u指定的用户是否允许从127.0.0.1登录(本地 socket 和 TCP 是两个 host),用mysql -h 127.0.0.1 -u...强制走 TCP,比改localhost用户更安全 - 如果用免密 SSH,确保
~/.ssh/id_rsa权限是600,且目标机器/home/$user/.ssh/authorized_keys没有多余空格或换行 - 脚本里所有密码别明文写死,用
mysql_config_editor存加密凭据,然后mysql --login-path=slave_check
真正麻烦的是 GTID 模式下 Seconds_Behind_Master 偶尔为 NULL 却复制正常,这时候得 fallback 查 gtid_executed 和 gtid_purged 差值——但那是另一层同步健康度判断了。











