复制延迟,无声的瘟疫
每个 DBA 都经历过这个时刻:监控显示从库有 300 秒的延迟,告警在响,而问题始终是同一个 — 为什么?
Seconds_Behind_Master(或 MySQL 8 中的 Seconds_Behind_Source)是一个二元指标:有延迟或没有延迟。它不会告诉你原因。是一个大规模的 DELETE 批处理?缺乏并行性?一个 800 KB 的事务阻塞了 SQL 线程?要找出答案,你需要 SSH 访问主库、正确的 mysqlbinlog 二进制文件、时间以及大量的 grep 操作。
PmaControl 现在将这一切自动化了。
新功能:Binlog 分析
工作原理
从任何从库的 slave/show 页面,你现在可以:
- 直接在延迟图表上选择时间范围(点击并拖动)或通过日期时间字段选择
- 一键启动分析 — 一切在后台运行
- 实时查看进度,逐步展示
- 查看完整报告,包含交互式图表和详细指标
- 收到 Telegram 通知,附带摘要信息
幕后发生了什么
当你启动分析时,PmaControl 执行一个 13 步流水线:
[21:15:02] ✓ init — 分析 #42 — slave=85 master=106 range=[20:27:51 → 20:29:27]
[21:15:02] ✓ master_info — 主库: prod-db-01 — 10.68.68.106:3306
[21:15:02] ✓ version — 版本: 8.0.44
[21:15:03] ✓ ssh — SSH 已连接到 10.68.68.106
[21:15:04] ✓ find_binlogs — 找到 1 个 binlog 文件: mysql-bin.046508
[21:15:18] ✓ download — 已下载 mysql-bin.046508 — 101.0 MB
[21:15:18] ✓ binary — 使用: mysqlbinlog-8.0 — Ver 8.0.42
[21:15:45] ✓ parse_gtid — 解析 36284 个事务,总计 97.2 MB
[21:16:12] ✓ parse_dml — I:148,659 U:191,867 D:115,853 = 456,379 行,涉及 148 个数据库
[21:16:38] ✓ parse_volume — 97 秒的数据,峰值 612 txn/s,峰值 1807 KB/s
[21:16:39] ✓ parse_ddl — 无 DDL — 100% DML 基于行的复制
[21:16:39] ✓ store — 报告存储成功
[21:16:39] ✓ cleanup — 清理完成 — 分析结束
每个步骤都在 UI 中实时可见,详细展示正在发生的事情。再也不用猜测传输是否在进行中或解析是否卡住了。
正确版本的正确二进制文件
一个经典的陷阱:使用 MariaDB 的 mysqlbinlog 来读取 MySQL 8 的 binlog,或反过来。事件被标记为 "Ignorable",基于行的数据变得不可读。
PmaControl 附带 6 个静态编译的 mysqlbinlog 二进制文件:
| 二进制文件 | 覆盖版本 |
|---|---|
mysqlbinlog-5.6 |
MySQL 5.5、5.6、Percona 5.6 |
mysqlbinlog-5.7 |
MySQL 5.7、Percona 5.7 |
mysqlbinlog-8.0 |
MySQL 8.0 |
mysqlbinlog-8.4 |
MySQL 8.4 LTS |
mysqlbinlog-9.2 |
MySQL 9.x Innovation |
mysqlbinlog-mariadb |
MariaDB 10.x、11.x、12.x |
选择是自动的:PmaControl 从主库的指标中读取 version 变量,并选择最接近的兼容二进制文件。
分析报告
每秒数据量图表
主图表显示两个叠加的系列:
- 蓝色柱状图:每秒数据量(KB/s)(每秒
transaction_length的总和) - 橙色折线:每秒事务数
这是 DBA 的第一反应:延迟是来自一次性峰值还是持续的吞吐量?图表立即给出答案。
MTS 并行度指标
这是分析真正有价值的地方。PmaControl 解析每个 GTID 事件中的 last_committed 和 sequence_number 字段来计算:
- 顺序事务百分比 — 那些
sequence_number = last_committed + 1的事务,无法被多线程从库并行化 - 最大并行组大小 — 实际可以同时运行多少个事务
- 组分布 — 1 个、2 个、3 个……事务的组各有多少
具体示例:如果 31% 的事务是顺序的,最大并行度为 7,那么即使配置了 16 个 replica_parallel_workers,大多数也会处于空闲状态。建议很明确:在主库上启用 binlog_transaction_dependency_tracking = WRITESET。
大事务检测
大事务是复制延迟的头号杀手。一个 834 KB 的事务触及 6,171 行,会在其整个持续时间内阻塞 SQL 应用线程 — 所有其他事务都排在它后面等待。
PmaControl 统计:
- 大于 100 KB 的事务
- 大于 500 KB 的事务
- 最大的事务(附带其内容:哪些表、多少行)
Top 表
报告列出了修改最多的 30 张表,包含 INSERT/UPDATE/DELETE 分类。这里经常能发现有害的模式:批处理使用 DELETE FROM table WHERE ...; INSERT INTO table ... 来"刷新"数据,而不是使用 INSERT ... ON DUPLICATE KEY UPDATE 或更小的事务。
自动建议
基于指标,PmaControl 生成具体的建议:
- "顺序事务比例为 31.3%。建议启用
binlog_transaction_dependency_tracking = WRITESET。" - "3 个事务 > 500 KB。大事务会阻塞 SQL 应用线程。"
- "修改了 148 个数据库。多租户模式可能导致复制热点。"
这些不是泛泛的建议 — 它们是从你实际 binlog 中的数据计算得出的。
Telegram 通知
分析完成后,摘要自动通过 Telegram 发送:
Binlog 分析完成
从库: replica-prod-01
主库: master-prod-01 (8.0.44)
范围: 2026-04-13 20:27:51 → 2026-04-13 20:29:27
━━━━━━━━━━━━━━━━━━━
大小: 101.0 MB | 事务: 36,284 | 持续时间: 96s
DML: I:148,659 U:191,867 D:115,853 = 456,379 行
峰值: 612 txn/s | 均值: 378.0 txn/s
顺序: 31.3% | 最大并行度: 7
大事务: 123 >100K, 3 >500K (最大 815 KB)
数据库: 148
━━━━━━━━━━━━━━━━━━━
• 高写入吞吐量(峰值 612 txn/s)。确保 replica_parallel_workers >= 8。
• 顺序事务比例为 31.3%。建议启用 WRITESET。
• 3 个事务 > 500 KB 阻塞了 SQL 应用线程。
值班 DBA 在手机上就能获得采取行动所需的一切信息。
技术架构
Binlog 获取:像 IO 线程一样
PmaControl 不使用 SSH 获取 binlog。它使用 mysqlbinlog --read-from-remote-server,通过 MySQL 协议连接到主库,与从库的 IO 线程完全一样。PmaControl 现有的 MySQL 凭据就足够了 — 不需要在主库上配置 SSH 密钥。
mysqlbinlog --read-from-remote-server \
--host=10.105.1.11 --port=3306 \
--user=pmacontrol --password=*** \
--raw --result-file=/tmp/analysis/ \
mysql-bin.1054495
如果 PmaControl 能连接到主库的 MySQL(它已经在做监控),就能获取 binlog。无需额外配置。
智能 Binlog 文件发现
一台生产主库可能有数千个 binlog 文件(我们在开发过程中遇到过 2,712 个文件)。扫描每个文件以找到时间范围会慢得不可接受。
两步策略:
-
从从库位置锚定 — 从
SHOW SLAVE STATUS读取Master_Log_File以知道当前的 binlog。同时查询主库的SHOW MASTER STATUS以考虑复制延迟。这给出一个窄窗口,而不是扫描所有 2,712 个文件。 -
二分查找 — 在这个窗口内,通过
mysqlbinlog --stop-position=500(只读取头部)探测每个文件的首个时间戳。使用二分查找,在 100 个候选文件中找到正确的文件只需 7 次探测而非 100 次。
结果:在拥有 2,712 个文件的主库上,binlog 发现只需 2 秒而非数分钟。
6 个静态二进制文件及其原因
PmaControl 附带了每个主要版本预编译的 mysqlbinlog 二进制文件。这源于一个技术教训:不兼容的 mysqlbinlog 不会产生错误 — 它会产生静默的错误结果。
真实案例:一个 MariaDB 的 mysqlbinlog 读取 MySQL 8.0 的 binlog 时,将基于行的事件标记为 "Ignorable" 并跳过它们。事务计数从 36,284 降到 0。没有显示任何错误。
mysqlbinlog 5.6/5.7 Bug:--raw 忽略 --stop-datetime
开发过程中发现的一个陷阱:在 --raw --read-from-remote-server 模式下,mysqlbinlog 5.6 和 5.7 版本静默忽略 --start-datetime 和 --stop-datetime 选项。进程不会在请求的日期停止,而是像 IO 线程一样永远等待新事件。
PmaControl 的解决方案:使用不带时间过滤器的 --raw(下载完整文件后退出),仅在本地解析时应用时间范围过滤。每个文件添加 120 秒超时作为安全网。
带实时进度的异步管道
分析通过 Glial CLI 在后台运行(php App/Webroot/index.php slave runBinlogAnalysisCli <id>)。前端每 2 秒轮询状态,以终端风格显示进度。progress JSON 字段存储了 13 个阶段的每一个及其时间戳。
结果存储
所有内容都持久化在 binlog_analysis 表中:
- 每秒数据量(JSON)
- Top 表(JSON)
- 并行度分布(JSON)
- 建议(JSON)
结果可以随时从分析历史中访问。
实际使用场景
"凌晨 3 点的从库延迟"
监控显示凌晨 3 点有一个延迟峰值。第二天早上,DBA 在图表上选择 02:55-03:10 的范围并启动分析。结果:一个 port_flux 刷新批处理在 148 个数据库中执行单个事务的 DELETE + INSERT 15,000 行。解决方案:拆分为 500 行的事务。
"为什么从库追不上来?"
尽管有 8 个并行工作线程,延迟仍在增长。分析显示 35% 的顺序事务和最大并行度为 5。解决方案:在主库上启用 WRITESET 并增加到 16 个工作线程。
"这个批处理对复制的影响是什么?"
在生产环境运行迁移批处理之前,分析预发布环境中类似的 binlog 以估算复制影响。
使用方法
- 打开 PmaControl → Slave → Show 查看你的从库
- 在延迟图表上点击并拖动以选择时间范围
- 点击 "Analyze Binlogs"
- 实时观看步骤展开
- 查看报告,检查建议
- 在 Telegram 上接收摘要
就是这么简单。不需要手动 SSH,不需要 mysqlbinlog | grep | awk | sort,不需要维护脚本。一键诊断复制延迟。
评论 (0)
暂无评论。
发表评论