暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL日志之redo log

手机用户6300 2024-08-24
100

redo log是什么

redo log也叫重做日志,是Innodb存储引擎生成的日志,记录的是物理级别上的页修改操作,为MySQL提供了崩溃恢复的能力,实现了事务的持久性。

InnoDB的事务采用了WAL技术(Write-Ahead Logging)既先写日志,再写磁盘。MySQL每执行一条DML语句,先将记录写入内存分配redo log buffer中,后续再一次性将redo log buffer中的内容写到redo log文件中,而被修改的数据页由checkpoint机制保证最终落盘。

为什么引入redo log

存在的问题

首先Innodb是以页为单位来进行磁盘IO,页的大小默认为16KB。在需要访问页时,要先将页从磁盘上缓存到内存中的Buffer Pool这个缓冲池中。所有数据的变更都是要在这个缓冲池中进行处理。

变更之后的页就形成了脏页,缓冲池会以一定的频率(checkPoint机制)将脏页刷新到磁盘。缓冲池的目的是有效减轻CPU和磁盘之间的速度差带来的性能影响。

但是由于脏页刷入磁盘不是每次变更后立即触发的,而是由master线程间隔一段时间去处理的,这就可能在事务提交之后刚写完缓冲区,此时MySQL宕机了,就会丢失这部分数据,这不符合事务的持久性要求。

如果在页变更后立即刷入磁盘又会影响性能,因为修改一个字节都会刷新16KB的数据到磁盘上,而且有些事务会涉及到多个页的数据,将这些页刷入磁盘需要进行多次随机IO操作是十分耗时的。

此时的解决方案就是先将变更的内容记录下来,例如:将第2页面中偏移量为50处的字节值由0变为1,此时可以记录为:将0号表空间的2页面的偏移量为50处的值更新为1。

redo log流转过程

redo log的好处

  • 降低刷盘频率:变更日志先行存入redo log buffer,脏页刷盘和redo log buffer刷盘时机可控;
  • 日志占用空间小:存储表空间ID、页号、偏移量和需要更新的值。
redo log崩溃恢复

刷盘策略

redo log的写入为了减少刷盘频率需要先写入内存的redo log buffer中,之后以一定的频率将buffer刷入到磁盘的redo log文件中去。

InnoDB 存储引擎为 redo log 的刷盘策略提供了三种策略,使用innodb_flush_log_at_trx_commit 参数配置,有以下三种取值:

取值含义优点缺点
0表示每次事务提交时不进行刷盘操作,由master线程每隔1s进行一次刷盘。IO效率高于1,低于2(注:0的IO频率是1s一次,2的IO频率由OS决定)数据库或操作系统宕机都会丢失1s数据,无法保证持久性
1表示每次事务提交时都将进行刷盘操作(默认值)。宕机不会丢失数据,保障了持久性效率最差
2表示每次事务提交时都只把redo log buffer内容写入操作系统的page cache,由OS决定什么时候同步到磁盘文件中。IO效率最高,仅数据库宕机不会丢失数据操作系统宕机会丢失1s数据,无法保证持久性

innodb_flush_log_at_trx_commit=0

事务过程中,redo log写入redo log buffer中,由master线程每隔1s调用fsync操作将buffer中的内容写到操作系统的page cache中。MySQL宕机会造成1s的事务丢失。
redolog=0

innodb_flush_log_at_trx_commit=1

事务提交时,主动刷盘redo log buffer的内容立刻同步到磁盘文件中,操作系统宕机不会丢失数据;
事务未提交时,操作系统宕机redo log buffer丢失也不会有损失,因为事务未提交不会持久化。
redolog=1

innodb_flush_log_at_trx_commit=2

事务提交就将redo log buffer中的内容写入page cache缓存,由操作系统决定什么时候将page cache的内容写入磁盘。此时MySQL宕机并不会丢失数据,但是操作系统宕机会丢失这1s的数据。
redolog=2

日志文件

redo log文件不止一个,而是以文件组的形式出现,文件大小其实就等于所有redo log文件大小之和。它们采用循环链表的方式向redo log日志文件组写入数据。

redolog文件组

在整个日志文件组中还有两个重要的属性:

  • write pos是当前记录的位置,一边写一边后移;
  • checkpoint是当前要擦除的位置,也是往后推移。

每次刷盘redo log记录到日志文件组中,write pos位置就会后移更新。

每次MySQL通过日志文件组恢复数据之后,这部分日志不再需要,会清空加载过的redo log记录,并把checkpoint后移更新。

write poscheckpoint之间为空闲部分可以用来写入新的redo log记录。

redo log组写入过程

redo log组被写满时,既write pos追上了checkpoint,此时不能再写入新的redo log,需要MySQL清空一些记录,留出新的空间。

redo log组写满

redo log相关配置

日志缓存区大小

默认16M,最大4096M,最小值为1M
mysql> show variables like'%innodb_log_buffer_size%';
+------------------------+---------+
| Variable_name          | Value   |
+------------------------+---------+
| innodb_log_buffer_size | 1048576 |
+------------------------+---------+
1 row in set (0.02 sec)

文件位置

默认值为.\,表示在数据库的数据目录(见配置datadir = C:\DevTools\mysql-5.7\data)下。
mysql> show variables like'%innodb_log_group_home_dir%';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_log_group_home_dir | .\    |
+---------------------------+-------+
1 row in set (0.02 sec)

文件数量

默认数量为2,命名方式如下:ib_logfile0ib_logfile1...
mysql> show variables like'innodb_log_files_in_group';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_log_files_in_group | 2     |
+---------------------------+-------+
1 row in set (0.02 sec)

日志文件大小

单个redo log文件设置大小,默认值为48M,最大值为512G既(innodb_log_files_in_group*innodb_log_file_size)不能大于512G
mysql> show variables like 'innodb_log_file_size';
+----------------------+----------+
| Variable_name        | Value    |
+----------------------+----------+
| innodb_log_file_size | 50331648 |
+----------------------+----------+
1 row in set (0.03 sec)

刷盘策略

mysql> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set (0.03 sec)
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论