MySQL-BinLog是如何做到数据同步的
分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程https://www.captainai.net/troubleshooter
MySQL 的 BinLog(Binary Log,二进制日志)做数据同步,核心原理可以概括为:主库将变更事件写入 BinLog → 从库拉取并回放这些事件。下面分步拆解。
一、BinLog 的三种格式
不同格式直接影响同步内容和效率:
| 格式 | 记录内容 | 优缺点 |
|---|---|---|
| STATEMENT | 执行的 SQL 语句 | 日志小,但可能有不确定性问题(如NOW()) |
| ROW | 每行数据的实际变更前后值 | 最精确,无歧义,但日志量大(推荐) |
| MIXED | 混合使用,自动选择 | 兼顾两者,但复杂场景可能不确定 |
数据同步通常使用ROW 格式,因为它能精确还原变更。
二、标准主从同步流程
主库 从库 | | | 1. 写 BinLog | | 2. 事件写入完成 | |----------------------> 3. I/O 线程拉取 BinLog | | 4. 写入 Relay Log | | 5. SQL 线程回放 | | 6. 数据变更详细步骤:
主库事务提交时
将变更事件按顺序写入 BinLog 文件(每个事务一个或多个事件)。从库 I/O 线程
连接到主库,请求从指定位置(文件名 + 偏移量)开始拉取 BinLog 事件。主库 Dump 线程
负责把 BinLog 事件发送给从库。从库接收
将事件先写入本地的Relay Log(中继日志)。从库 SQL 线程
读取 Relay Log,按照与原事务相同的顺序在从库执行这些事件。从库数据更新完成
从库最终与主库数据一致。
三、同步的定位机制(GTID vs 文件名+位置)
从库需要知道“已经同步到哪里了”,以便断点续传。
传统方式:记录
(binlog.000001, position 1234)
缺点:主从切换后找位置复杂。GTID(Global Transaction Identifier)(推荐)
每个事务有全局唯一 ID(如3E11FA47-71CA-11E1-9E33-C80AA9429562:23)。
从库只需告诉主库“我已执行了哪些 GTID”,主库自动发送缺失事务。
优点:主从切换、故障恢复更简单安全。
四、ROW 格式下如何精确同步行变更
比如执行UPDATE users SET age=30 WHERE id=100:
STATEMENT 格式:记录这条 SQL
ROW 格式(关键):
事件1: before image (id=100, age=25, name='张三') 事件2: after image (id=100, age=30, name='张三')从库直接应用“将 id=100 的行从 (25) 改为 (30)”,不依赖 SQL 语义。
这样即使主库有触发器、确定性函数,从库也能精确复制行状态。
五、半同步复制(提升一致性)
默认异步复制:主库提交后不等待从库确认,可能丢数据。
半同步复制:
主库提交事务 → 写 BinLog → 等待至少一个从库确认收到 → 才返回客户端 OK减少主从切换时的数据丢失风险。
六、同步延迟问题及常⻅原因
大事务:一个事务改 1000 万行,主库 BinLog 很大,从库回放慢
从库硬件差:I/O 或 CPU 不足
从库有读负载:同时处理查询和回放
ROW 格式下无主键的表:从库更新每行需要全表扫描,极慢
监控命令:SHOW SLAVE STATUS\G看Seconds_Behind_Master。
七、经典应用场景
除了主从复制,BinLog 还用于:
数据同步到异构系统:如使用 Canal、Debezium 消费 BinLog,写入 Kafka、Elasticsearch、Redis(Canal 模拟 MySQL 从库协议,拉取 ROW 格式事件并解析)
基于 BinLog 的备份恢复:全量备份 + BinLog 可实现时间点恢复(PITR)
总结一句话
BinLog 数据同步 =主库记录变更日志(ROW 格式最佳)→ 从库拉取并按顺序回放 → 通过 GTID 或位点定位进度,从而实现最终一致的副本。
