为什么从 redo log buffer 刷入 redo log file 不是一次磁盘 IO 操作

redo log

redo log 的作用就像是在记账时的临时小账本,先临时记录某人的账目变化情况,在之后将这个变化记录到真正的账本中。如此一来当需要记账的人很多时可以提高效率(比从账本中查找某人再记录效率高)。

在 MySQL 中,如果没有 redo log 更新语句成本最高的地方就是每次都要从表中找到对应数据行并对其修改,这一次次的磁盘 IO 操作是最耗时的,因此 redo log 的出现提高了效率,因为有大量更新语句时不会一次次操作磁盘写入表中,而是将这些操作临时记录在 redo log 中,在空闲时执行一次磁盘 IO 操作写入表中。

crash-safe 能力

redo log 也用于保证 crash-safe 能力,当我们将 innodb_flush_log_at_trx_commit参数值设为 1 时,每次事务提交都会将事务的 redo log 持久化到磁盘。

**实际在执行时,更新操作首先会记录在 MySQL 内存中的缓存区中的 redo log buffer,然后事务提交时执行持久化到磁盘的操作。当多个事务并行执行时,其中一个事务提交也会导致其他未提交的事务的 redo log 持久化到磁盘,**此时若 MySQL 异常重启,恢复数据时还要判断 redo log 中记录的每个事务的状态。(两阶段提交)

这样就可以保证事务提交后如果 MySQL 异常重启,redo log 数据不丢失(bin log 也有对应的参数设置,同时为了保证 bin log 和 redo log 的一致性,事务提交时采用两阶段提交,详见十、MySQL redo log 和 bin log 概述

看到这里就会有一个疑问,同标题所述,既然我们要保证 crash-safe 能力而设置为事务提交时 redo log 需要持久化到磁盘,那这跟直接写入表效率相差并不大吧,最多在一个事务有多个更新语句的时候表现的稍微高效一丢丢,但是如果有大量事务以及伴随的更新操作,那么一样会导致大量 redo log 持久化到磁盘的操作。

文件系统缓冲区

传统 Unix 系统在内核中都设有缓冲区,大多数的磁盘 IO 都会经过缓冲区缓冲再写入磁盘文件中。因此实际将数据写入到磁盘文件时,内核首先会将数据复制到缓冲区(注意,这里的缓冲区是操作系统级别的),如果缓冲区没写满,则不会进入输出队列,当缓冲区写满或者内核需要时,会将数据排入输出队列,从队首开始写入磁盘。这被称为延迟写

在这里插入图片描述

Unix 提供了sync、fsync、fdatasync三个函数
sync只是将所有修改过的块放入写队列,不管它是否写磁盘结束就返回
fsync会等待写磁盘结束才会返回。

O_DIRECT选项:O_DIRECT 选项是 Linux 文件写入中的一个选项,开启了这个选项以后,数据就可以跳过系统层的缓冲区,直接写入磁盘。

最后回到 redo log 上,根据 redo log 的需要,redo log 文件肯定没有开启 O_DIRECT 选项(否则跟直接写入表有什么区别呢)

因此可以看到,标题中并没有说是将 redo log buffer 写入 redo log 文件,而是用了“刷入”这个词,这是因为事务结束的时候 redo log 虽然要将数据持久化到磁盘,但是真正持久化的时候只是将数据刷入了文件系统缓冲区中,并没有真正执行一次磁盘 IO 操作。因此执行效率肯定比磁盘 IO 操作高。之后为了确保 redo log 写入磁盘,就通过 fsync 操作将数据写入磁盘。

文件系统缓冲区是系统级的,因此即便 MySQL 异常重启也不会影响数据恢复。

此时转不过弯的某些童鞋会发出疑问,既然 redo log 写入磁盘时会经过系统文件缓冲区而提高效率,那同样更新操作的时候那次写入表中的操作为什么一定是一次磁盘 IO 操作呢?

这是因为,一次更新操作在写入数据前,首先得找到表中对应的数据行,这必定会造成一次磁盘 IO 操作。

相关参数

innodb_flush_log_at_trx_commit:用来控制redo log刷新到磁盘的策略。
  1. 如果设置为 0,redo log buffer将每秒一次地写入 log file 中,并且 log file 的 flush (刷到磁盘)操作同时进行。该模式下,在事务提交的时候,不会主动触发写入磁盘的操作。该模式速度最快,但不太安全。
  2. 如果设置为 1,每次事务提交时 MySQL 都会把 redo log buffer 的数据写入 log file,并且 flush (刷到磁盘)中去。该模式是最安全的,但也是最慢的一种方式。
  3. 如果设置为 2,每次事务提交时 MySQL 都会把 redo log buffer 的数据写入 log file。但是 flush (刷到磁盘)操作并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操作。该模式速度较快,也比0安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值