【MySQL日志--redo log】

MySQL

MySQL 执行流程和缓冲池
MySQL 事务
MySQL 日志–redo log
MySQL 日志–undo log


本文参考尚硅谷康师傅的 MySQL课程


1、为什么需要 redo log

1.1、直接把事务的更改刷新到磁盘的缺点

  • InnoDB 是以页为单位对磁盘进行 I/O,当我们对页面的修改内容较少(例如一个字节)时,会浪费I/O性能
  • 一个事务中可能包含很多语句,改事务修改的业务可能不相邻,这就意味着在将某个事务修改的Buffer Pool中的页面刷新到磁盘时需要进行很多的随机I/O,随机Io比顺序I/O要慢

1.2、WAL

InnoDB引擎的事务采用了WAL技术(Write-Ahead Logging ),这种技术的思想就是先写日志,再写磁盘,只有日志写入成功,才算事务提交成功,这里的日志就是redo log

1.3、redo log 的优点

  • redo log 是顺序写入磁盘的
  • 事务执行过程中,redo log 不断记录

小贴士:
redo logbin log的区别,redo log是存储引擎层产生的,而bin log是数据层产生的。假设一个事务,对表做10万行的记录插入,在这个过程中,一直不断的往redo log顺序记录,而bin log不会记录,直到这个事务提交,才会一次写入到bin log文件中。

2、redo log 的组成

2.1、redo log buffer

在服务器启动时就向操作系统申请了一大片称之为redo log buffer的连续内存空间。这片内存空间被划分成若干个连续的redo log block。一个redo log block占用512字节大小。

参数设置:innodb_log_buffer_size:
redo log buffer 大小,默认 16M ,最大值是4096M,最小值为1M。

mysql> show variables like '%innodb_log_buffer_size%';
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+

log buffer


2.2、redo log file

保存在磁盘中,是持久的

redo log 流转过程:


redo log 流转过程


第1步:先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝
第2步:生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值
第3步:当事务commit时,将redo log buffer中的内容刷新到 redo log file,对 redo log file采用追加写的方式
第4步:定期将内存中修改的数据刷新到磁盘中

3、redo log 的刷盘策略

redo log的写入并不是直接写入磁盘的,InnoDB引擎会在写redo log的时候先写redo log buffer,之后以 一定的频率 刷入到真正的redo log file 中。这里一定的频率就是刷盘策略


redo log 的刷盘策略


注意:
redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中去,只是刷入到 文件系统缓存(page cache)中去(这是现代操作系统为了提高文件写入效率做的一个优化),真正的写入会交给系统自己来决定(比如page cache足够大了)。那么对于InnoDB来说就存在一个问题,如果交给系统来同步,同样如果系统宕机,那么数据也丢失了(虽然整个系统宕机的概率还是比较小的)

刷盘过程

innodb_flush_log_at_trx_commit ,该参数控制 commit提交事务时,如何将 redo log buffer 中的日志刷新到 redo log file 中。它支持三种策略

  • 设置为0 :表示每次事务提交时不进行刷盘操作。(系统默认master thread每隔1s进行一次 redo log 的同步)
  • 设置为1 :表示每次事务提交时都将进行同步,刷盘操作( 默认值 )
  • 设置为2 :表示每次事务提交时都只把 redo log buffer 内容写入 page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。
show variables like 'innodb_flush_log_at_trx_commit';

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.00 sec)

三种策略下的示意图

0


1


2


4、redo log file

4.1、参数设置

innodb_log_group_home_dir: 指定 redo log 文件组所在的路径,默认值为./

innodb_log_files_in_group: 指明redo log file的个数

mysql> show variables like 'innodb_log_files_in_group';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| innodb_log_files_in_group | 2 |
+---------------------------+-------+
#ib_logfile0
#ib_logfile1

innodb_flush_log_at_trx_commit:控制 redo log 刷新到磁盘的策略,默认为1

innodb_log_file_size:单个 redo log 文件设置大小,默认值为 48M 。最大值为512G,注意最大值指的是整个 redo log 系列文件之和,即(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 |
+----------------------+----------+

根据业务修改其大小,以便容纳较大的事务。编辑my.cnf文件并重启数据库生效,如下所示

[root@localhost ~]# vim /etc/my.cnf
innodb_log_file_size=200M  

4.2、日志文件组

从上边的描述中可以看到,磁盘上的redo日志文件不只一个,而是以一个日志文件组的形式出现的。这些文件以ib_logfile[数字](数字可以是0、1、2…)的形式进行命名,每个的redo日志文件大小都是一样的。

在将redo日志写入日志文件组时,是从ib_logfile0开始写,如果ib_logfile0写满了,就接着ib_logfile1写。同理,ib_logfile1.写满了就去写ib_logfile2,依此类推。如果写到最后一个文件该咋办?那就重新转到ib_logfile0继续写,所以整个过程如下图所示:
在这里插入图片描述
总共的redo日志文件大小: innodb_log_file_size × innodb_log_files_in_group

采用循环使用的方式向redo日志文件组里写数据的话,会导致后写入的redo日志覆盖掉前边写的redo日志?当然!所以InnoDB的设计者提出了checkpoint的概念。

4.3、checkpoint

在整个日志文件组中还有两个重要的属性,分别是write poscheckpoint

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

每次刷盘redo log记录到日志文件组中,write pos位置就会后移更新。每次MySQL加载日志文件组恢复数据时,会清空加载过的redo log记录,并把 checkpoint后移更新。write pos和checkpoint之间的还空着的部分可以用来写入新的redo log记录。

checkpoint
如果 write pos 追上 checkpoint ,表示日志文件组满了,这时候不能再写入新的 redo log记录,MySQL 得停下来,清空一些记录,把 checkpoint 推进一下。
checkpoint

5、小结

InnoDB的更新操作采用的是Write Ahead Log(预先日志持久化)策略,即先写日志,再写入磁盘。
小结

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值