【问题标题】:Why doesn't MySQL InnoDB redo log block writing need double write?为什么 MySQL InnoDB 重做日志块写入不需要双写?
【发布时间】:2022-01-09 01:26:29
【问题描述】:

MySQL InnoDB 重做日志块大小为 512 字节(可能是磁盘中的一个扇区)。我读了Are disk sector writes atomic?。看起来它取决于底层硬件来决定扇区写入是否是原子的。那么如果不是原子的,InnoDB redo log 怎么保证不会损坏呢?

假设磁盘中最后一个日志块未满,那么 InnoDB 引擎会向该块写入更多日志记录并将其刷新到磁盘。突然断电导致只有部分块已写入磁盘。由于该块的校验和不匹配。其他之前提交的事务在服务器重启后会丢失。

【问题讨论】:

  • MDEV-14425 上进行了相当长且有趣的讨论,我们可以看到via the implementation 使用了操作系统物理块大小(并且是原子的,在 O_DIRECT for linux >=3.14(和其他?))。
  • @danblack - 听起来像是答案,而不仅仅是评论。
  • @danblack 谢谢。我会接受你的回答。

标签: mysql innodb storage-engines redo-logs


【解决方案1】:

当事务提交时,mysql 会强制将 redo log block(512b) 刷新到磁盘,如果 log block 未满,mysql 会在刷新到磁盘之前用零填充 blcok。

如果flush动作成功,则事务提交成功; 如果flush动作有错误,事务提交将失败;

因此,如果事务提交成功,则事务的重做日志必须已刷新到磁盘。

如果redo block的校验和不匹配,说明redo log block的flush动作有错误(比如掉电),这个block中redo log的transcation肯定是失败的。

所以当mysql掉电恢复时,提交的事务不会丢失,因为成功的事务必须成功地将他的重做日志刷新到磁盘。

最后,为什么重做日志块大小是 512 字节? 因为它尝试使用磁盘原子写入(磁盘扇区大小为 512 字节)来加快速度并减少不匹配的校验和。 如果磁盘不支持 512byte 原子写入,也没关系。

【讨论】:

  • 我认为这很重要。该块可能具有先前已提交的事务。下一次失败的刷新可能会破坏块并导致先前提交的事务丢失。所以我认为块写入必须是原子的。
  • @xnervwang 如果一个块已经提交了事务,那么这个块肯定已经刷到磁盘了,刷完之后不会再写任何其他事务的重做日志,直到被重用。跨度>
猜你喜欢
  • 2017-02-26
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
相关资源
最近更新 更多