Binlog(Binary Log,归档日志)
为什么需要 Binlog?
- Binlog 是 MySQL 中的二进制日志,用于记录数据库的所有写操作(
INSERT
、UPDATE
、DELETE
等)
1. 主从复制
- 作用:是 MySQL 主从复制的核心,主库将 Binlog 发送给从库,从库重放这些操作以保持数据同步。
- 场景:读写分离、负载均衡和高可用性。
2. 数据恢复
- 作用:Binlog 记录了所有写操作,可用于数据丢失时或误操作时恢复数据。
- 场景:通过回放 Binlog,可将数据库恢复到特点时间点或事务点。
3. 审计
- 作用:Binlog 记录了所有写操作的详细信息,可用于审计数据库变更。
- 场景:追踪数据变更历史,满足合规要求。
4. 增量备份(只备份从上次备份以来发生变化的数据)
- 作用:Binlog 用于增量备份,减少备份时间和存储空间。
- 场景:定期备份 Binlog,结合全量备份实现高校数据恢复。
5. 数据同步
- 作用:Binlog可用于将数据同步到其他系统,如数据仓库或缓存。
- 场景:保持不同系统间的数据一致性。
Binlog 是什么?
1. 适用对象
- Binlog 是 MySQL 的 Server 层实现的日志,所有存储引擎都可使用。
2. Binlog 的内容(记录逻辑操作)
- 事件类型:如
INSERT
、UPDATE
、DELETE
、DDL
(如CREATE TABLE
)等。 - 操作数据:受影响的行数据(旧值和新值)。
- 事务信息:事务的开始和提交时间、事务 ID 等。
- 时间戳:操作发生的时间。
3. Binlog 的格式
Statement-Based(基于语句)
- 记录实际的 SQL 语句(逻辑操作)。
- 优点:日志文件小,记录简单。
- 缺点:动态函数不一致问题(如
UUID()
、NOW()
等),导致主从不一致。
Row-Based(基于行)
- 记录每一行数据的变更(旧值和新值)。
- 优点:数据一致性高,适合复杂操作。
- 缺点:日志文件较大。
Mixed【默认】(混合模式)
- 根据情况进行选择,自动切换到另外两种模式。
- 平衡了数据一致性与日志大小。
4. Binlog 的写入方式
追加写
- 写满一个文件,就创建一个新文件继续写,不会覆盖之前的记录,保存的是全量日志。
对比 Redo Log 的循环写,为什么 Binlog 采用追加写?
- Redo Log 目的保证事务持久性和崩溃恢复,只记录未写入磁盘的数据和物理日志,是事务级别的写入,已经刷入磁盘的数据不进行擦除会浪费空间。
- Binlog 的目的是主从复制和备份恢复,是语句(或行)级别的写入,采用追加写,追加写的方式保证了日志的持续性和历史性,不会因为日志满了而覆盖掉有用的数据。用户通常需要依赖Binlog来回溯数据库的操作历史。
Binlog 实现主从复制
MySQL 的主从复制依赖于 Binlog,即记录 MySQL 上所有变化并以二进制形式保存在磁盘上,复制的过程是将 Binlog 中的数据从主库传输到从库上。且这个过程一般是异步的——主库上执行事务操作的线程不会等待复制 Binlog 的线程同步完成。
在完成主从复制后,就可以实现主写从读的模式了,这样即使写请求会锁表或者锁记录,也不会影响读请求的执行。
1. Binlog 主从复制过程
1.1. 写入 Binlog
- 主库写 Binlog 日志,并以两阶段提交的方式提交事务,并更新本地缓存。
- 详细过程:MySQL 主库在收到客户端提交事务的请求后,先写入 Binlog,再提交事务,更新存储引擎中的数据,事务提交完成后,返回给客户端“操作成功”的响应。
1.2. 同步 Binlog
- 把 Binlog 复制到所有从库中,每个从库把 Binlog 写到暂存日志中。
- 详细过程:从库创建一个特定的 I/O 线程,连接主库的
log dump
线程,来接收主库的 Binlog 日志,再把 Binlog 信息写入 Relay Log 的中继日志里,再返回给主库“复制成功”的响应。
1.3. 回放 Binlog
- 回放 Binlog,并更新存储引擎中的数据。
- 详细过程:从库创建一个用于回放 Binlog 的线程,去读 Relay Log 中继日志,然后回放 Binlog 更新存储引擎中的数据,最终实现主从的数据一致性。
2. 从库是不是越多越好?
- 不是的,从库的数量增加,从库连接的 I/O 线程也会增加,主库也要创建同样多的
log dump
线程处理复制的请求,对主库资源消耗增高,同时也受限于主库的网络带宽。 - 所以实际中,1 个主库一般跟 2~3 个从库(1 主 2 从 1 备),即一主多从 MySQL 集群结构。
3. MySQL 主从复制模型
3.1. 同步复制
- MySQL 主库提交事务的线程要等待所有从库的复制成功响应,才返回客户端结果,在实际项目中基本不用。
- 缺点:性能差;可用性差——主库和所有从库任何一个数据库出问题,都会影响业务。
3.2. 异步复制(默认模型)
- MySQL 主库提交事务的线程并不会等待 Binlog 同步到各从库,就返回客户端。
- 缺点:一旦主库宕机,数据就会丢失。
3.3. 半同步复制(MySQL 5.7 以后)
- 介于同步与异步复制之间,事务线程不用等待所有从库复制成功响应,只要一部分复制成功响应就可以返回客户端结果。
- 优点:兼顾了同步与异步复制的优点,即使主库宕机,至少有一个从库有最新的数据,且性能也很好。
Binlog 持久化过程
1. Binlog Cache
- Binlog Cache—线程缓冲区:MySQL 给每个线程分配一片内存区域用于缓冲 Binlog,即 Binlog Cache,参数
binlog_cache_size
用于控制单个线程内 Binlog Cache 所占内存的大小,若超过了这个参数,则暂存到磁盘中。 - 先写入 Binlog Cache:事务执行时,先将日志写到 Binlog Cache(Server 层的 cache),事务提交时,再将 Binlog Cache 写到 Binlog 文件中。
- 事务的串行执行:当一个线程开始执行一个新事务(通过
BEGIN
或START TRANSACTION
)时,MySQL 会确保该线程之前的事务(如果有)已经提交或回滚。也就是说,一个线程不能同时并行执行多个事务。 - Binlog 的写入原子性:由于一个线程在同一时间只能处理一个事务,因此该事务的 Binlog 日志必须保证一次性完整写入,而不能拆分为多个,即 Binlog 需要保证事务的原子性:一个事务的所有操作要么全部生效,要么全部不生效。如果不保证 Binlog 的原子性,从库在重放时,可能会将拆分后的日志当作多个独立的事务执行,破坏了主库事务的原子性。
2. 持久化过程
每个线程将缓冲在 Binlog Cache 中的日志文件,最终写到同一个 Binlog 文件。
write
:将日志写入到 Binlog 文件(OS 中的 page cache 中),但未持久化到磁盘,因为不涉及磁盘 I/O 操作,write 的写入速度很快。fsync
:将数据持久化到磁盘中,因涉及磁盘 I/O 操作,写入较慢,故频繁fsync
会导致磁盘 I/O 升高。
3. sync_binlog
参数——控制 MySQL 的 Binlog 刷盘频率
- = 0 时(默认):每次提交事务时,只
write
,不fsync
,后续由 OS 择机将数据持久化到磁盘。
-
- 性能:最好。
- 风险:最大,一旦发生异常重启,还未持久化到磁盘中的数据就会全部丢失。
- = 1 时:每次提交事务时,先
write
,后马上执行fsync
。
-
- 性能:最差。
- 风险:最小,即使异常重启,最多丢失一个事务的 Binlog。
- = N(N > 1)时:每次提交事务时,都
write
,积累 N 个事务后再fsync
。
-
- 性能与风险都适中,可以根据系统进行特定配置,一般的设置范围: 100 ~ 1000。