前言

Write-Ahead Log(预先日志持久化):在持久化一个数据页之前,先将内存中相应的日志页持久化。

事务有四大特性: 原子性、一致性、隔离性和持久性。

  • 事务的隔离性由 锁机制 实现。

  • 而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。

    • REDO LOG称为 重做日志 ,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性。
    • UNDO LOG 称为 回滚日志 ,回滚行记录到某个特定版本,用来保证事务的原子性、一致性。

有的DBA或许会认为 UNDO 是 REDO 的逆过程,其实不是。

  • redo log是物理日志,记录的是数据页的物理变化,undo log不是redo log的逆过程

  • undo log是逻辑日志,对事务回滚时,只是将数据库逻辑地恢复到原来的样子。

  • redolog:是存储引擎层(innodb)生成的日志,记录的是”物理级别”上的页修改操作,比如页号xxx、偏移量yyy写入了'zzz”数据。主要为了保证数据的可靠性;

  • undo log:是存储引擎层(innodb)生成的日志,记录的是逻辑操作日志,比如对某一行数据进行了INSERT语句操作,那么undolog就记录一条与之相反的DELETE操作。主要用于事务的回滚(undo log记录的是每个修改操作的逆操作)和 一致性非锁定读(undo log回滚行记录到某种特定的版本—MVCC,即多版本并发控制)。

redo 日志

为什么需要redo

好处和特点

好处

  • redo日志降低了刷盘频率

  • redo日志占用的空间非常小

特点

  • redo日志是顺序写入磁盘的

  • 事务执行过程中,redo log不断记录

redo log组成

Redo log可以简单分为以下两个部分:

  • redo log buffer: 保存在内存中 (重做日志的缓冲 )

  • redo log file: 保存在硬盘中 (重做日志文件)

redo log buffer:参数设置:innodb_log_buffer_size:
redo log buffer 大小,默认 16M ,最大值是4096M,最小值为1M。
可以通过show variables like '%innodb_log_buffer_size%'查看

redo整体流程

  • 第1步:先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝

  • 第2步:生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值

  • 第3步:当事务commit时,将redo log buffer中的内容刷新到 redo log file,对 redo log file采用追加写的方式

  • 第4步:定期将内存中修改的数据刷新到磁盘中

redo刷盘策略

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

redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中去,只是刷入到 文件系统缓存(page cache)中去(这是现代操作系统为了提高文件写入效率做的一个优化),真正的写入会交给系统自己来决定(比如page cache足够大了)。那么对于InnoDB来说就存在一个问题,如果交给系统来同
步,同样如果系统宕机,那么数据也丢失了(虽然整个系统宕机的概率还是比较小的)。
针对这种情况,InnoDB给出 innodb_flush_log_at_trx_commit 参数,该参数控制 commit提交事务
时,如何将 redo log buffer 中的日志刷新到 redo log file 中。它支持三种策略:

  • 设置为0 :表示每次事务提交时不进行刷盘操作。(系统默认master thread每隔1s进行一次重做日志的同步)

  • 设置为1 :表示每次事务提交时都将进行同步,刷盘操作( 默认值 )

  • 设置为2 :表示每次事务提交时都只把 redo log buffer 内容写入 page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。

三种刷盘策略

1. Innodb_flush_log_at_trx_commit=1

1. Innodb_flush_log_at_trx_commit=2

1. Innodb_flush_log_at_trx_commit=0

写入redo log buffer过程

Mini-Transaction

一个事务可以包含若干条语句,每一条语句其实是由若干个 mtr 组成,每一个 mtr 又可以包含若干条redo日志,画个图表示它们的关系就是这样:

redo 日志写入log buffer

每个mtr都会产生一组redo日志,用示意图来描述一下这些mtr产生的日志情况


不同的事务可能是 并发 执行的,所以 T1 、 T2 之间的 mtr 可能是 交替执行 的。

redo log block


redo log file

相关参数设置

  • innodb_log_group_home_dir :指定 redo log文件组所在的路径,默认值为 ./ ,表示在数据库的数据目录下。MySQL的默认数据目录( var/lib/mysql )下默认有两个名为 ib_logfile0ib_logfile1 的文件,log buffer中的日志默认情况下就是刷新到这两个磁盘文件中。此redo日志文件位置还可以修改。

  • innodb_log_files_in_group:指明redo log file的个数,命名方式如:ib_logfile0iblogfile1iblogfilen。默认2个,最大100个。

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

日志文件组

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

checkpoint


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

参考文献

文章部分内容引用自宋红康老师的Mysql高级课程,在此表示感谢,如有侵权,请联系站长进行删除
<声明>:

谁都不是生下来就会的,都不是三体人,知识也可以遗传,我们的东西都是学习到的,所以每个人的知识体系难免有老师的身影,先学习后模仿,才能学会,至于笔记,摘抄部分我感觉难免,学会了就是自己的!

分类: mysql

浙公网安备33011302000604

辽ICP备20003309号