赞
踩
这里的刷盘不是指将内存中的数据刷新到磁盘,而是指从Redo日志位于内存中的缓冲区(redo log buffer)刷新到位于磁盘中的文件区(redo log file).
page cache
)中去。真正的刷入磁盘会交给操作系统来决定关键参数
数据库中innodb_flush_log_at_trx_commit
参数就控制了在事务提交时,如何将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时,提交一次刷盘一次
参数为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用时最多,提交一次事务就刷盘一次虽然用时多,但最能保证事务的持久性
Mini-Transaction
)MTR
包含一组redo日志,这一组日志是不可分割的一个整体(即使系统崩溃也不可分割)MTR
,一个MTR
可以包含若干个redo日志:buf_free
变量标记当前到了那个块存储块结构
ib_logfile0
和ib_logfile1
,每次刷盘都是将数据刷新到这两个文件内日志文件组属性
日志文件组有两个重要属性:
write pos
:标识当前记录位置,并向后移动checkpoint
:擦除当前位置的记录,并向后移动这两个属性就像是两个指针,在同一个环上移动,一个标记当前数据写到哪了,另一个是擦除数据。
write pos
会后移checkpoint
会后移,经过上篇和本片博客的介绍,我们已经了解了Redo日志的作用和刷盘原理、存储形式等,包括Innodb存储引擎的日志持久化策略
整个过程如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。