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

考虑到一个问题,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中的缓冲机制及其实现方式。首先,我需要确认自己对缓冲的理解是否正确。缓冲通常是指在处理数据时使用两个缓冲区,一个用于前台操作,另一个用于后台处理,以减少等待时间并提高效率。这在图形学或者I/O操作中比较常见,但MySQL中的缓冲可能有所不同。 接下来,我得回忆一下MySQL的相关知识。记得InnoDB存储引擎有缓冲池(Buffer Pool),这是内存中的一块区域,用于缓存数据和索引。可能缓冲和缓冲池有关?比如在入数据时,先入内存缓冲区,再刷盘到磁盘,这样可能涉及到缓冲机制。 另外,日志系统如redo log和binlog入也可能使用缓冲。比如,redo log入过程可能有多个缓冲区,一个正在入,另一个在准备刷盘,这样可以避免阻塞。或者binlog在同步到从库时,主库可能有一个缓冲区用于累积事件,另一个用于发送,从而实现并行处理。 还需要考虑页面清理线程(Page Cleaner Thread)。当缓冲池中的脏页需要刷盘时,可能使用缓冲机制来避免阻塞用户线程。比如,一个缓冲区用于继续处理新的操作,另一个被清理并入磁盘。 不过,用户提供的参考引用中提到MySQL 8.0的C API用于复制事件流,这可能与binlog缓冲有关。比如,主库生成binlog事件时,可能使用两个缓冲区,一个在填充当前事件,另一个用于发送给从库,这样主库可以持续处理事务而不必等待网络传输。 另外,需要确认缓冲在MySQL中的具体实现是否存在官方文档支持。可能需要查阅MySQL文档或相关源码。比如,InnoDB的缓冲池管理、redo log入机制、binlog的组提交等都可能涉及缓冲技术。 总结一下,可能的实现点包括:缓冲池的脏页入、redo log的缓冲区切换、binlog的组提交和发送机制,以及复制过程中的缓冲应用。需要将这些点组织起来,用中文解释清楚,并确保LaTeX格式正确,同时生成相关问题。</think>### MySQL缓冲机制解析 MySQL缓冲机制主要用于优化I/O密集型操作,其核心思想是通过内存缓冲区降低磁盘操作延迟。以下从三个层面分析其工作原理: 1. **InnoDB缓冲池的层管理** - 主缓冲池($Buffer\ Pool$)采用分段LRU算法管理数据页 - 操作先修改内存中的脏页($dirty\ page$),后台线程异步刷盘 - 通过$doublewrite\ buffer$实现安全页入: $$page_{memory} \xrightarrow{flush} doublewrite\ buffer \xrightarrow{fsync} data\ file$$ 2. **日志系统的缓冲设计** - Redo log使用循环缓冲区: ```mermaid graph LR A[活跃缓冲区] -->|满后切换| B[备用缓冲区] B -->|后台刷盘| C[(磁盘)] ``` - Binlog通过组提交($Group\ Commit$)优化: $$事务1+事务2+... \xrightarrow{缓冲} 批量fsync$$ 3. **复制流程中的缓冲应用** - 主库使用$binlog\ cache$临时存储事件[^1] - 从库通过$relay\ log\ buffer$进行中继缓冲 - 并行复制时采用多工作线程+缓冲队列模式 ### 实现关键点 - 内存屏障保证缓冲区切换原子性 - 刷盘阈值动态调整($innodb_flush_neighbors$) - 异步I/O线程池管理($innodb_write_io_threads$)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值