MySQL~Redo刷盘策略、LogBuffer缓存池和LogFile日志文件理解

刷盘策略
  • Innodb在写Redo日志的时候,是先写入redo log buffer 中,然后再按照一定频率刷新到redo log file中。
  • 这里的 一定频率 有多个选择,这些选择对应的就是不同的刷盘策略.

这里的刷盘不是指将内存中的数据刷新到磁盘,而是指从Redo日志位于内存中的缓冲区(redo log buffer)刷新到位于磁盘中的文件区(redo log file).

  • redo log buffer 刷盘到redo log file的过程也不是真正刷到磁盘中去,只是刷入到 文件缓存系统(page cache)中去。真正的刷入磁盘会交给操作系统来决定

关键参数
数据库中innodb_flush_log_at_trx_commit参数就控制了在事务提交时,如何将buffer中的日志数据刷新到file中.

该参数支持三种策略:

  • 参数值为0:提交事务也不进行刷盘操作
  • 参数值为1:提交事务一次就刷盘一次默认刷盘策略
  • 参数值为2:每次提交事务时,只会将buffer中的内容写入页面缓存中,不会在将页面缓存中的数据刷盘到file中

查看默认的刷盘参数值:

mysql> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set, 1 warning (0.03 sec)

可以看到参数值为1,即默认提交一次就刷盘一次

这里必须提到的一个情况是,即使我们将参数设为0,什么也不做,在数据库中也有一个后台线程,默认每1秒就帮我们自动刷盘一次:
在这里插入图片描述
没有提交的事务在执行过程中写下的redo log记录,也可能会被后台线程刷盘,如下图:
在这里插入图片描述
除了后台线程自动刷盘外,还有一种情况也会刷盘,就是当buffer中的记录数据大小达到最大值(16M)的一半的时候,也会自动刷盘。

总结:

  • 事务提交时会刷盘
  • 后台线程每隔1秒自动刷盘
  • 记录达到buffer空间一半时刷盘
不同刷盘策略演示

参数值为1时,提交一次刷盘一次

在这里插入图片描述
参数为2时,将buffer中的数据刷新到page cache中间缓存中,不会进一步更新到file中
在这里插入图片描述
我们分别对参数为1和参数为2时进行操作,看相同操作下哪个用掉的时间更短。
参数1演示


创建数据库
CREATE DATABASE atguigudb3;

使用数据库
USE atguigudb3;

创建test_load表作为初始数据
CREATE TABLE test_load(
a INT,
b CHAR(80)
)ENGINE=INNODB;

使用存储过程添加数据
这里是每insert一次就提交一次事务,过会调用储存过程是可以看看多长时间 
DELIMITER//
CREATE PROCEDURE p_load(COUNT INT UNSIGNED)
BEGIN
DECLARE s INT UNSIGNED DEFAULT 1;
DECLARE c CHAR(80)DEFAULT REPEAT('a',80);
WHILE s<=COUNT DO
INSERT INTO test_load SELECT NULL,c;
COMMIT;
SET s=s+1;
END WHILE;
END //
DELIMITER;

先查看一下当前刷盘参数是多少
mysql> SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set, 1 warning (0.03 sec)

当前是1,则看1的过程
调用存储过程生成数据  3万次操作就是3万个事务提交

mysql> CALL p_load(30000);
Query OK, 0 rows affected (27.41 sec) 

可以看到,参数为1时用掉了27

参数2演示

先清空一下数据
mysql> truncate table test_load;
Query OK, 0 rows affected (0.03 sec)
查看是否清空 为0 清空
mysql> select count(*) from test_load;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)
修改为2
mysql> SET GLOBAL innodb_flush_log_at_trx_commit = 2;
Query OK, 0 rows affected (0.00 sec)

查看是否修改为2
mysql> SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 2     |
+--------------------------------+-------+
1 row in set, 1 warning (0.00 sec)
开始操作
mysql> CALL p_load(30000);
Query OK, 0 rows affected (19.52 sec)

参数为2时,用掉了19.5

参数0演示

直接设置为0
mysql> set global innodb_flush_log_at_trx_commit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 0     |
+--------------------------------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> call p_load(30000);
Query OK, 0 rows affected (14.81 sec)
相同操作 参数为0 用掉了14.8

从演示结果来看,参数为0和2用时差不多,即策略一和策略三是相同的,默认的策略一即参数为1用时最多,提交一次事务就刷盘一次虽然用时多,但最能保证事务的持久性

Redo log buffer缓存区
  • 对底层页面的一个原子访问称为一个mtr,即迷你事务(Mini-Transaction
  • 一个MTR包含一组redo日志,这一组日志是不可分割的一个整体(即使系统崩溃也不可分割)
  • 一个事务可以包含若干个MTR,一个MTR可以包含若干个redo日志:

在这里插入图片描述

  • Redo日志的log buffer 区域是一个整体的存储空间,这个空间又被划分成一个个的存储块,写入日志时是顺序写入,这些存储块也是按顺序被填满
  • buf_free变量标记当前到了那个块
    在这里插入图片描述
  • 一个事务中包含多个MTR,就包含多组redo日志,这些组日志会并发的插入到存储块中,没有顺序
    在这里插入图片描述

存储块结构

  • 一个存储块是512个字节,由日志头、日志体、体制尾组成。头占12,尾占8,所以一个块的实际存储空间是496个字节
    在这里插入图片描述
Redo log file日志文件
  • MySQL默认目录中,有两个文件ib_logfile0ib_logfile1,每次刷盘都是将数据刷新到这两个文件内
  • Redo日志文件有很多个,一般以日志文件组的形式出现,文件统一命名,格式是ib_logfile+数字,从0开始
  • 日志文件组中每个文件大小相同
  • 每次写入从0开始,然后是1,2,3…
    在这里插入图片描述

日志文件组属性

日志文件组有两个重要属性:

  • write pos:标识当前记录位置,并向后移动
  • checkpoint:擦除当前位置的记录,并向后移动

这两个属性就像是两个指针,在同一个环上移动,一个标记当前数据写到哪了,另一个是擦除数据。

在这里插入图片描述

  • 每次刷盘时,会添加新的数据记录到文件组中,write pos 会后移
  • 每次恢复数据时,会清空加载过的数据记录,checkpoint会后移,
  • 两个指针之间空的部分写入新记录
总结

经过上篇和本片博客的介绍,我们已经了解了Redo日志的作用和刷盘原理、存储形式等,包括Innodb存储引擎的日志持久化策略

整个过程如下:
在这里插入图片描述

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值