《MySQL——redo log 与 binlog 写入机制》

本文详细介绍了MySQL的binlog和redolog写入机制,以及组提交和WAL机制如何提升系统性能。通过调整sync_binlog和innodb_flush_log_at_trx_commit参数,可以在保证数据安全的前提下减少磁盘IOPS。同时,利用binlog_group_commit_sync_delay和binlog_group_commit_sync_no_delay_count参数,可以进一步优化binlog的写盘策略,实现更高的TPS。

WAL机制告诉我们:只要redo log与binlog保证持久化到磁盘里,就能确保MySQL异常重启后,数据可以恢复。

下面主要记录一下MySQL写入binlog和redo log的流程。

binlog写入机制

1、事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。

2、binlog cache,系统为每个线程分配了一片binlog cache内存,参数binlog_cache_size控制单个线程内binlog cache大小。如果超过了这个大小就要暂存磁盘

3、事务提交的时候,执行器把binlog cache里完整的事务写入binlog中。并清空binlog cache

4、每个线程都有自己的binlog cache,共用一份binlog文件

5、write,是把日志写入到文件系统的page cache,内存中,没有持久化到磁盘,所以速度比较快,图中的fsync是将数据持久化到磁盘,占用磁盘的IOPS
在这里插入图片描述

关于何时write、fsync是由参数sync_binlog控制的:

1、sync_binlog = 0时,每次提交事务都只write,不fsync;
2、sync_binlog = 1时,每次提交事务都会执行fsync;
3、sync_binlog = N(N>1)时,表示每次提交事务都write,但累积N个事务后才fsync。

sync_binlog控制binlog真正刷盘的频率,对于一个IO非常大的情景,这个数字调大可以提高性能,但是如果容错率非常低的情况下,必须设为1.(sync_binlog设置为N对应的风险是:如果主机发生异常重启,会丢失最近N个事务的binlog日志)

redo log写入机制

事务在执行过程中,生成的redo log是要先写到redo log buffer的。

redo log buffer里面的内容并不需要每次生成后都要持久化到磁盘中。

如果事务执行期间MySQL发生异常重启,那么这部分日志就丢了。由于事务并没有提交,所以这时日志丢了也不会有损失。

事务没提交的时候,redo log buffer部分日志也是有可能被持久化到磁盘中的。
在这里插入图片描述
上面三个颜色表征了redo log可能的三种状态:

1、存在redo log buffer中,物理上是在MySQL进程内存中,即红色部分;

2、写到磁盘(write),但是没有持久化(fsync),物理上实在文件系统的page cache里面,即黄色部分;

3、持久化到磁盘,对应的是hard disk,也就是图中的绿色部分;

前两步是写内存,最后一步是磁盘IO,所以要在page cache够大且不影响写入page cache前将redo log 持久化到磁盘 。

为了控制redo log 的写入策略,InnoDB提供了innodb_flush_log_at_trx_commit参数,他有三种可能取值:

1、设置为0,每次事务提交的时候都只是把redo log留在redo log buffer中;
2、设置为1,每次事务提交的时候都只是把redo log直接持久化到磁盘;
3、设置为2,每次事务提交时都只是把redo log写到page cache;

与binlog不同,binlog是每个线程都有一个binlog cache,而redo log是多个线程共用一个redo log buffer。

InnoDB有一个后台线程,每隔1s,就会把redo log buffer中的日志,调用write写到文件系统的page cache,然后调用fsync持久化到磁盘,事务执行过程中的redo log也是直接写在redo log buffer上的,所以,未提交的事务的redolog也可能被持久化到磁盘。

还有两种场景也会导致没有提交的事务的redo log写入到磁盘中:

情形1:

redo log buffer占用的空间即将达到innodb_log_buffer_size一半的时候,后台线程会主动写盘。

(这里只是write,没有fsync)

情形2:

并行的事务提交的时候,顺带将这个事务的redo log buffer持久化到磁盘。

(事务A执行一半,部分redo log到buffer中;事务B提交,且 innodb_flush_log_at_trx_commit ,会把redo log buffer里的log全部持久化到磁盘中)

补充说明

两阶段提交在时序上redo log先prepare 再写binlog,最后再把redo log commit;

innodb_flush_log_at_trx_commit 设置成 1,prepare阶段redo log就已经落盘。所以redo log再commit的时候就不需要fsync了,只会write到文件系统的page cache中就够了。

sync_binlog 和 innodb_flush_log_at_trx_commit都设置为1,即一个事务完整提交前,需要等待两次刷盘,一次是redo log(prepare阶段),一次是binlog。

组提交机制实现大量的TPS

首先介绍日志逻辑序列号(log sequence number,LSN)的概念。LSN是单调递增的,每次写入长度length的redo log,LSN的值就会加上length。

三个并发事务(trx1,trx2,trx3)在prepare阶段,都写完redo buffer,并持久化到磁盘。

对应的LSN为50、120、160.

对应流程:

1、trx1第一个到达,被选为这组的leader;

2、等trx1要开始写盘的时候,这个组里面已经有三个事务,这时候LSN也变成了160;

3、trx1去写盘的时候,LSN=160;trx1返回时,所有LSN<= 160的redo log都被持久化到磁盘中;

4、trx2与trx3直接返回。

总结:

一次组提交中,组员越多,节约磁盘IOPS的效果越好。如果是单线程,就只能一个事务对应一次持久化操作

两阶段提交
两阶段提交细化

这样保证binlog也可以组提交了。由于step3速度快,所以集合到一起的binlog比较少,所以binlog的组提交效果不如redo log组提交。

提升binlog效果:

--1.binlog_group_commit_sync_delay :b表示延迟多少微秒后才调用fsync;
--2.binlog_group_commit_sync_no_delay_count :表示累积多少次以后才调用fsync;

理解WAL机制

WAL机制是减少磁盘写,可是每次提交事务都要写redo log和binlog ,磁盘读写次数没有变少。

所以WAL机制主要得益于两个方面:

--1、redo log和binlog都是顺序写,磁盘的顺序写比随机写速度要快
--2、组提交机制,可以降低磁盘IOPS消耗

如何提升IO性能瓶颈

1、设置binlog_group_commit_sync_delaybinlog_group_commit_sync_no_delay_count参数,减少binlog的写盘次数。这个方法是基于“额外故意等待”来实现的,可能会增加语句的响应时间,但是不会丢失数据

2、将sync_binlog设置为大于1的值(100~1000)。不过会有主机掉电时丢binlog日志的风险

3、将 innodb_flush_log_at_trx_commit 设置为2。会有主机掉电丢数据的风险

<think> 我们正在讨论MySQLRedo LogBinlog如何协同工作来保证数据一致性。用户的问题集中在这两个日志组件的协同机制上。根据引用内容,特别是引用[5]中提到的两阶段提交(2PC)是协同工作的核心。下面我将详细解释这一过程。 整体思路: 1. 明确Redo LogBinlog的基本职责(先单独说明) 2. 重点阐述两阶段提交的过程(核心协同机制) 3. 说明崩溃恢复时如何利用这些日志 4. 最后总结协同工作的意义 引用说明: - 引用[1][2][3]提到这三种日志的基本作用 - 引用[4][5]特别强调了两阶段提交和协同工作,尤其是引用[5]详细对比了三种日志的特性,并明确提到两阶段提交 回答结构: 1. 前置知识:两种日志的定位差异 - Redo Log(InnoDB引擎层):物理日志,记录数据页的修改,保证持久性 - Binlog(Server层):逻辑日志,记录SQL语句或行变更,用于复制和备份 2. 协同核心:两阶段提交(2PC)流程 - 分Prepare和Commit两个阶段 - 具体步骤分解 3. 崩溃恢复时的处理 - 如何通过日志状态决定提交或回滚 4. 协同工作的意义 - 保证主从数据一致性 - 确保崩溃恢复后数据一致 需要特别注意的技术细节: - XA事务规范:两阶段提交是分布式事务的经典解决方案,MySQL内部用它协调两种日志 - Binlog的三种格式(STATEMENT/ROW/MIXED)对协同机制的影响(以ROW格式为例说明) 下面开始组织回答内容: </think> ### MySQL Redo LogBinlog协同工作机制详解 MySQL通过**两阶段提交(2PC)协议**协调Redo LogBinlog,确保事务持久性主从数据一致性,其核心流程如下: ```mermaid graph LR T[事务提交] --> S1[Prepare阶段] S1 -->|1. 写入Redo Log prepare标记| R[Redo Log] S1 -->|2. 写入Binlog| B[Binlog] B --> S2[Commit阶段] S2 -->|3. 写入Redo Log commit标记| R S2 -->|4. 刷盘完成| D[返回客户端成功] ``` #### 一、协同工作流程(两阶段提交) 1. **Prepare阶段** - InnoDB将事务修改写入Redo Log,状态标记为`prepare` $$ \text{Redo Log: } \langle \text{TRX_ID}, \text{prepare}, \text{数据页修改} \rangle $$ - 此时事务已持有锁,但**未真正提交**[^5] 2. **Binlog写入阶段** - Server层生成Binlog(格式为`STATEMENT`/`ROW`/`MIXED`) $$ \text{Binlog: } \langle \text{TRX_ID}, \text{SQL语句/行变更} \rangle $$ - Binlog写入成功后调用`fsync()`刷盘[^4] 3. **Commit阶段** - InnoDB将Redo Log状态更新为`commit` $$ \text{Redo Log更新: } \langle \text{TRX_ID}, \text{commit} \rangle $$ - 释放事务持有的锁,返回客户端成功 #### 二、崩溃恢复时的数据一致性保障 当系统崩溃后重启,通过对比日志状态恢复数据: ```mermaid graph TD C[崩溃恢复] --> Check1{检查Redo Log} Check1 -->|存在prepare记录| Check2{检查Binlog} Check2 -->|Binlog完整| Commit[重做事务] Check2 -->|Binlog缺失| Rollback[回滚事务] Check1 -->|无prepare记录| Ignore[忽略] ``` - **场景1:Binlog完整存在** 说明事务已完整提交,Redo Log重放修改(即使数据页未刷盘) - **场景2:Binlog不存在或截断** 说明事务未成功提交,通过Undo Log回滚修改[^5] #### 三、关键协作设计 1. **写入顺序保证** $$ \text{Redo Log prepare} \rightarrow \text{Binlog} \rightarrow \text{Redo Log commit} $$ 严格顺序确保崩溃时可通过Binlog状态决策 2. **刷盘控制** - Redo Log:采用循环写入,`innodb_flush_log_at_trx_commit=1`时每次提交刷盘 - Binlog:`sync_binlog=1`时保证每次提交刷盘[^4] 3. **XA事务规范** 两阶段提交符合分布式事务标准,为跨数据库一致性提供基础 #### 四、实际应用中的关键参数 | 参数 | 作用 | 建议值 | |------|------|--------| | `innodb_flush_log_at_trx_commit` | Redo Log刷盘策略 | 1(每次提交刷盘) | | `sync_binlog` | Binlog刷盘频率 | 1(每次提交刷盘) | | `binlog_format` | Binlog记录格式 | ROW(数据一致性最强) | > ⚠️ **特别注意**:在异步复制场景中,从库通过重放Binlog实现数据同步,因此Binlog的完整写入是主从数据一致性的基石[^5]。 --- ### 相关问题 1. **如何配置MySQL参数来优化Redo LogBinlog写入性能?** 2. **在分布式事务场景下,MySQL的XA协议如何两阶段提交协同工作?** 3. **Binlog的ROW格式STATEMENT格式对数据一致性有何不同影响?** 4. **MySQL崩溃恢复过程中,如何验证Redo LogBinlog的一致性?** 5. **在高并发写入场景下,两阶段提交可能成为性能瓶颈,有哪些优化方案?**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾牙慧者

欢迎请作者喝奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值