mysql 为何需要Double Write?有redo log还不够吗?

本文解释了Mysql为何需要Doublewrite机制来保障数据一致性,尤其是在redo log应用过程中可能遇到的问题。通过详细介绍Doublewrite的工作原理及其如何与redo log配合工作,帮助读者理解这一重要机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

考虑到一个问题,Mysql为何需要Double write来双写数据到数据块?redo log不是已经记录了所有的数据历史记录了吗?

要弄明白这个问题,首先先要了解一下mysql redo log里面记录的是什么?

日志分为物理日志和逻辑日志,物理日志就是直接记录数据/数据,记录被修改的page的偏移量,优点就是不依赖原page的内容,用日志的内容可以直接覆盖到磁盘上面,而缺点就是占用的空间太多,比如新增一个btree索引或者一个update操作。逻辑日志只是在关系表上面的元操作,比如update一行数据,delete一行数据等,优点就是比较简洁而且占用的空间要小,缺点就是需要依赖原page内容,而且会有部分执行和操作一致性的问题。

mysql 的redo log将物理日志和逻辑日志相结束 ,取其利,避其害,从而达到一个更好的状态。具体为:

 A. 物理到page. 将操作细分到页级别。为每个页上的操作单独记日志。
     比如,一个Insert分别在2个B-Tree的节点上做了插入操作,那么就分别为每一个页的操作记录一条日志。
  B. Page内采用逻辑的日志。比如对一个B-Tree的页内插入一条记录时,物理上来说要修改Page Header的 内容(如,页内的记录数要加1),要插入一行数据到某个位置,要修改相邻记录里的链表指针,要修改Slot的属性等。从逻辑上来说,就是在这个页内插入了一行记录。因此Page内的逻辑日志只记录:’这是一个  插入操作’和’这行数据的内容‘。

这样的一个redo log取长补短,难道就没有什么问题了吗?其实数据的一致性问题仍然没有解决,如果在redo log应用到磁盘 时,在写一个Page到磁盘时发生了故障,可能导致Page Header的记录数被加1了(表示已此page已恢复完成),但是页内的逻辑日志在发生了故障,这时数据就不一致了。好在这个问题被缩小到了一个页中,比较好解决。而mysql就是用double write来的方法来解决此问题。

由于innodb page是16K,一般系统page是4k,当有个update语句需要对业内记录加1,当第一个4k中记录加1后,系统宕机,重启恢复时候,innodb 不知道从哪里给记录加1,如果给16k里所有记录都加1,就会导致第一个4k里面记录加2,必然导致数据不一致,这个时候double write buffer就解决了这个问题。

  Double Write的思路很简单:

  A. 在覆盖磁盘上的数据前,先将Page的内容写入到磁盘上的其他地方(InnoDB存储引擎中的doublewrite  buffer,这里的buffer不是内存空间,是持久存储上的空间).

  B. 然后再将Page的内容覆盖到磁盘上原来的数据。

  如果在A步骤时系统故障,原来的数据没有被覆盖,还是完整的。
  如果在B步骤时系统故障,原来的数据不完整了,但是新数据已经被完整的写入了doublewrite buffer.  因此系统恢复时就可以用doublewrite buffer中的新Page来覆盖这个不完整的page.


参考:http://www.zhdba.com/mysqlops/2012/04/06/innodb-log2/

<think>嗯,用户想了解MySQL中一条update语句的执行过程,特别是buffer pool中各组件如redo log、undo log、change buffer的交互。首先,我需要回忆一下MySQL的架构,特别是InnoDB存储引擎的部分。可能得从客户端发送SQL请求开始,到解析、优化、执行,再到存储引擎层面的处理。 然后重点在buffer pool。Buffer pool是内存中的一块区域,用来缓存数据和索引。当执行update时,数据页如果不在buffer pool中,需要先从磁盘加载进来。这里可能需要提到change buffer,它用于缓存非唯一索引的更新,避免立即读磁盘,但用户的问题是关于update的,所以可能需要说明change buffer的应用场景。 redo log是用于崩溃恢复的,记录物理修改。undo log则是记录事务前的数据镜像,用于回滚和MVCC。这两者在事务处理中很重要,需要详细解释它们如何协作。 具体步骤大概是:事务开始,生成undo log,修改数据页,记录redo log入change buffer(如果有涉及非唯一索引的更新),然后事务提交时redo log刷盘,undo log可能留在内存或刷盘。需要确保这些步骤正确,以及各组件之间的顺序和依赖关系。 可能需要考虑是否有图,但用户希望最好有图,但作为文本回复,可能需要用文字描述结构或用ASCII图示意。例如,展示客户端、server层、InnoDB引擎层,buffer pool中的各个部分,redo log buffer,磁盘上的redo log文件,undo log段,change buffer的结构等。 还需要注意术语的准确性,比如redo log buffer和redo log文件的区别,undo log存放在undo tablespace中,change buffer是buffer pool的一部分。另外,在更新数据时,先undo log,再修改数据页,然后记录redo log。对于二级索引的更新,如果页不在内存,则使用change buffer,避免立即读入。 可能还需要提到脏页,即被修改但未刷回磁盘的数据页,由后台线程定期刷新。以及checkpoint机制,确保redo log的空间重用。 用户可能想了解整个流程的细节,比如两阶段提交,或者如何保证ACID特性,但问题主要是update的执行和组件交互,所以需要围绕buffer pool中的各个组件展开,可能不需要深入事务管理的所有细节。 要确保逻辑清晰,步骤明确,分阶段说明:解析、执行引擎、InnoDB处理,数据加载到buffer pool,生成undo log,修改数据,记录redo log,处理索引更新(可能用change buffer),事务提交时的处理,redo刷盘,binlog入(如果涉及主从的话),但用户没有提到binlog,可能需要判断是否要包含。不过问题重点在buffer pool中的组件,可能不需要涉及binlog,除非与redo log的两阶段提交有关。 需要检查是否有遗漏的组件,比如doublewrite buffer,但用户的问题可能不涉及这个,所以可以忽略。主要关注redo、undo、change buffer和buffer pool的关系。 总结步骤可能如下: 1. 客户端发送update语句。 2. Server层解析、优化,生成执行计划。 3. InnoDB查找数据页,如果不在buffer pool,则从磁盘加载。 4. 生成undo log,用于回滚和MVCC。 5. 修改buffer pool中的数据页,标记为脏页。 6. redo logredo log buffer,记录数据页的修改。 7. 如果有二级索引的更新,并且索引页不在内存,将更改记录到change buffer。 8. 事务提交时,redo log buffer刷盘,确保持久性。 9. 后台线程将脏页刷回磁盘,可能根据checkpoint机制。 10. undo log在事务提交后,可能被purge线程清理。 在解释过程中,需要明确各个组件的交互顺序,比如先undo,再改数据页,再redo。同时,change buffer的使用场景和过程。 可能需要指出,在步骤7中,如果索引页在buffer pool中,直接更新;否则使用change buffer。而change buffer的合并发生在索引页被读取到buffer pool时,或者后台线程定期合并。 关于图表,可以用文字描述各部分的连接,例如: Buffer Pool包含: - 数据页 - Change Buffer(用于非唯一索引的更新) - 其他结构如自适应哈希索引等 当更新发生时: 1. 数据页在Buffer Pool?是→修改;否→从磁盘加载到Buffer Pool。 2. 生成Undo Log,存入Undo Log段(在系统表空间或独立undo表空间)。 3. 修改数据页,记录Redo LogLog Buffer。 4. 若涉及二级索引,检查索引页是否在Buffer Pool: - 是→直接更新; - 否→将更新记录到Change Buffer。 5. 提交事务时,Redo Log Buffer刷入磁盘的Redo Log文件。 6. 之后,脏页由后台线程刷回磁盘,Change Buffer中的变更在相关页被访问时合并。 这样应该能覆盖用户的问题点。需要确保术语正确,流程合理,各组件的作用和交互清晰。</think>以下是对 MySQL 中 `UPDATE` 语句执行过程的详细解释,重点围绕 Buffer Pool 及其组件的交互(文字示意图描述): --- ### **一、整体流程概览** 1. **客户端请求**:发送 `UPDATE` SQL 语句。 2. **Server 层处理**:解析、优化,生成执行计划。 3. **InnoDB 引擎层**:处理数据修改,与 Buffer Pool 交互。 4. **事务提交**:持久化修改(Redo Log 刷盘)。 5. **后台操作**:脏页刷盘、Change Buffer 合并等。 --- ### **二、Buffer Pool 核心组件交互** #### **1. 数据加载到 Buffer Pool** - 若目标数据页**不在 Buffer Pool**,则从磁盘加载到内存。 - 若数据页已存在,直接修改内存中的副本(称为**脏页**)。 #### **2. Undo Log 生成** - **作用**:记录修改前的数据镜像,用于事务回滚和 MVCC(多版本并发控制)。 - **入位置**:Undo Log 存储在系统表空间或独立的 Undo Tablespace 中。 - **流程**: 1. 事务开始时,生成 Undo Log 记录。 2. 修改数据前,将旧值入 Undo Log。 #### **3. 修改数据页** - 直接更新 Buffer Pool 中的**数据页**,标记为脏页。 #### **4. Redo Log 记录** - **作用**:确保事务的持久性(物理日志,记录页修改)。 - **入位置**:先入 **Redo Log Buffer**(内存),事务提交时刷盘。 - **流程**: 1. 修改数据页后,生成 Redo Log 记录到 Redo Log Buffer。 2. 事务提交时,通过 `fsync` 将 Redo Log Buffer 入磁盘的 Redo Log 文件。 #### **5. Change Buffer 处理(针对非唯一索引)** - **作用**:延迟非唯一索引的更新,避免立即加载索引页到内存。 - **入条件**: - 仅适用于非唯一索引。 - 当索引页**不在 Buffer Pool** 时,将更新操作缓存到 Change Buffer。 - **合并时机**: - 后续读取该索引页到 Buffer Pool 时,合并 Change Buffer 中的修改。 - 后台线程定期合并。 --- ### **三、交互流程图(文字示意)** ```plaintext 客户端 │ ▼ Server 层(解析、优化) │ ▼ InnoDB 引擎层 ├─ 1. 检查数据页是否在 Buffer Pool? │ ├─ 否 → 从磁盘加载到 Buffer Pool │ └─ 是 → 直接修改 │ ├─ 2. 生成 Undo Log(记录旧值) │ ├─ 3. 修改 Buffer Pool 数据页(标记为脏页) │ ├─ 4. 记录 Redo LogRedo Log Buffer │ └─ 5. 处理索引更新: ├─ 唯一索引 → 直接更新(需加载索引页) └─ 非唯一索引 → 若页不在内存,入 Change Buffer │ 事务提交时: ├─ Redo Log Buffer → 刷盘(fsync) └─ 返回客户端成功 │ 后台线程: ├─ 脏页刷盘(Checkpoint 机制) └─ Change Buffer 合并到磁盘索引页 ``` --- ### **四、关键组件协作总结** | 组件 | 作用 | 交互顺序 | |----------------|--------------------------------------|-------------------------| | **Buffer Pool**| 缓存数据页,加速读 | 数据页加载、修改、标记脏页 | | **Undo Log** | 支持回滚和 MVCC | 修改前记录旧值 | | **Redo Log** | 保证事务持久性 | 修改后记录新值,提交刷盘 | | **Change Buffer** | 优化非唯一索引更新 | 延迟索引页更新,异步合并 | --- ### **五、附加说明** 1. **脏页刷盘**:由后台线程通过 Checkpoint 机制将脏页入磁盘。 2. **Change Buffer 合并**:发生在索引页被读取到 Buffer Pool 时,或后台线程异步处理。 3. **崩溃恢复**:通过 Redo Log 重放未刷盘的修改,通过 Undo Log 回滚未提交的事务。 通过上述流程,MySQL 在保证 ACID 的同时,利用内存优化(Buffer Pool)和异步机制(Change Buffer)提升性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值