MySQL redo log和binlog刷盘时机的个人理解

在MySQL中redo log和binlog在数据保护方面有着至关重要的作用,是有需要花点时间去研究一下这两个玩意儿。以下结论是个人一家之见,看官们请酌情观看,有异议之处欢迎进行交流,万分感谢!

1.正常情况下两阶段提交配合组提交的流程如下:
在这里插入图片描述

我个人理解是在双一模式下的流程,每个事务提交时都需要进行fsync刷盘,其执行过程才如上图所示。
然而在配合两个参数sync_binlog和innodb_flush_log_at_trx_commit,上图会有所调整。

一.innodb_flush_log_at_trx_commit在非1的情况下,步骤三可以忽略。
a.innodb_flush_log_at_trx_commit=0,redo log日志条目写入到redo log buffer中,MySQL即认为redo log已完成写入,即redo log prepare状态,可以进行下一步动作。b.innodb_flush_log_at_trx_commit=2,redo log日志条目写入到文件系统缓存page cache,MySQL即认为已完成redo log完成写入,即redo log prepare状态,可以进行下一步动作。此时的刷盘由MySQL的后台主线程和操作系统层进行完成。

二.sync_binlog在非1的情况下,步骤四可以进行忽略。
a.sync_binlog=0,binlog只需要写入到binlog cache即可进行下一步,此刻MySQL会认为binlog已完成写入,redo log和binlog达成一致,redo log可以commit。
b.sync_binlog=N(N>1),每个事务的binlog都写入到binlog cache,攒够N个事务之后,集中fsync刷盘(由后台主线程处理),此刻MySQL会认为binlog已完成写入,redo log和binlog达成一致,redo log可以commit。

此时我们需要借助binlog组提交的延迟来验证我们的结论:

####双一模式下,每个事务均需要刷盘
mysql> show variables like '%sync_binlog%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 1     |
+---------------+-------+
1 row in set (0.00 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.01 sec)

mysql> 
mysql> show variables like '%binlog_group%';
+-----------------------------------------+---------+
| Variable_name                           | Value   |
+-----------------------------------------+---------+
| binlog_group_commit_sync_delay          | 1000000 |
| binlog_group_commit_sync_no_delay_count | 10      |
+-----------------------------------------+---------+
2 rows in set (0.00 sec)

mysql> select * from words_bak;
+----+--------+
| id | word   |
+----+--------+
|  1 | hello  |
|  2 | world  |
|  3 | python |
|  4 | c      |
|  5 | c++    |
|  6 | php    |
|  7 | B      |
|  8 | mysql  |
|  9 | pg     |
| 10 | oracle |
| 11 | go     |
+----+--------+
11 rows in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from words_bak where id = 11;
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (1.00 sec)


此刻事务提交时需要花费1.00 sec,因为binlog_group_commit_sync_delay设置的是1s,binlog_group_commit_sync_no_delay_count和binlog_group_commit_sync_delay满足其中一条即可

###将sync_binlog参数设置为5
mysql> set global sync_binlog=5;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%sync_binlog%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 5     |
+---------------+-------+
1 row in set (0.00 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.00 sec)

mysql> show variables like '%binlog_group%';
+-----------------------------------------+---------+
| Variable_name                           | Value   |
+-----------------------------------------+---------+
| binlog_group_commit_sync_delay          | 1000000 |
| binlog_group_commit_sync_no_delay_count | 10      |
+-----------------------------------------+---------+
2 rows in set (0.01 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from words_bak;
+----+--------+
| id | word   |
+----+--------+
|  1 | hello  |
|  2 | world  |
|  3 | python |
|  4 | c      |
|  5 | c++    |
|  6 | php    |
|  7 | B      |
|  8 | mysql  |
|  9 | pg     |
| 10 | oracle |
+----+--------+
10 rows in set (0.00 sec)

mysql> delete from words_bak where id = 10;
Query OK, 1 row affected (0.01 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)


此时事务提交只需要0.00sec,可以初步判定提交的瞬间未刷盘,但是提交成功了。如果继续测试,你会发现因为sync_binlog=5,在后续的2-4的事务,commit都是很快,第5个事务commit所消耗的时间是1s左右。

sync_binlog和binlog_group_commit_sync_no_delay_count的关联和差异

sync_binlog表示累积N个事务后开始进行刷盘。在参数binlog_group_commit_sync_delay为非0的情况下,MySQL会认为刷盘的过程中需要按照某些条件进行延迟刷盘。
假设场景1:
binlog_group_commit_sync_delay=1000000(1 秒) ; —>1s后刷盘
binlog_group_commit_sync_no_delay_count = 2; —>并发同时提交的事务达到2个进行刷盘
假设当前只有一个事务,这个事务触发了MySQL刷盘动作,但是此时不满足binlog_group_commit_sync_no_delay_count=2,刷盘的时候会按照1s的延迟就行刷盘。

mysql> show variables like '%sync_binlog%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 3     |
+---------------+-------+
1 row in set (0.02 sec)

mysql> show variables like '%binlog_group%';
+-----------------------------------------+---------+
| Variable_name                           | Value   |
+-----------------------------------------+---------+
| binlog_group_commit_sync_delay          | 1000000 |
| binlog_group_commit_sync_no_delay_count | 2       |
+-----------------------------------------+---------+
2 rows in set (0.00 sec)

mysql> delete from words where id = 112;
Query OK, 1 row affected (0.00 sec)

mysql> delete from words where id = 113;
Query OK, 1 row affected (0.00 sec)


此时下一个事务例如delete from words where id = 114 commit才会触发binlog刷盘,此时才会进入binlog_group_commit_sync_delay和binlog_group_commit_sync_no_delay_count的延迟刷盘的逻辑,这时候开启两个并行的窗口,这两个窗口同时commit提交
窗口1:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from words where id = 114;
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.10 sec)

窗口2:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from words where id = 115;
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.10 sec)

观察可以发现commit均使用了0.1sec,不是之前的1 sec了,此刻符合binlog_group_commit_sync_no_delay_count=2,无须延迟1sec进行刷盘,耗时0.1 sec。

假设场景2:
打开双一,即每个事务均会刷盘,此刻关闭binlog_group_commit_sync_no_delay_count即设置为0,binlog_group_commit_sync_delay=1000000,此刻每个事务commit时均会消耗1秒左右

mysql> show variables like '%binlog_group%';
+-----------------------------------------+---------+
| Variable_name                           | Value   |
+-----------------------------------------+---------+
| binlog_group_commit_sync_delay          | 1000000 |
| binlog_group_commit_sync_no_delay_count | 0       |
+-----------------------------------------+---------+
2 rows in set (0.01 sec)

mysql> show variables like '%sync_binlog%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 1     |
+---------------+-------+
1 row in set (0.01 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.00 sec)

mysql> delete from words where id = 137;
Query OK, 1 row affected (1.00 sec)

mysql> delete from words where id = 138;
Query OK, 1 row affected (1.00 sec)

mysql> delete from words where id = 139;
Query OK, 1 row affected (1.01 sec)

mysql> delete from words where id = 140;
Query OK, 1 row affected (1.00 sec)

mysql> delete from words where id = 141;
Query OK, 1 row affected (1.00 sec)

mysql> delete from words where id = 142;
Query OK, 1 row affected (1.00 sec)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值