MySQL日志——redo log和bin log的刷盘时机详解

2024-03-31 06:52

本文主要是介绍MySQL日志——redo log和bin log的刷盘时机详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们先简单了解一下大致的刷盘时机,然后配合两阶段提交和组提交来看

redo log的刷盘时机

  1. MySQL 正常关闭时;
  2. 当 redo log buffer 中记录的写入量大于 redo log buffer内存空间的一半时,会触发落盘;
    PS:为什么这里要到一半就要刷了,因为redo log buffer是一个环状的内存结构,会被反复利用
  3. InnoDB 的后台线程每隔 1 秒,将 redo log buffer 持久化到磁盘。
  4. 由系统参数innodb_flush_log_at_trx_commit 参数控制。

其中,innodb_flush_log_at_trx_commit 参数控制,可取的值有:0、1、2,默认值为 1,这三个值分别代表的策略如下:
1、当设置该参数为 0 时,表示每次事务提交时将 redo log 留在 redo log buffer 中 ,该模式下在事务提交时不会主动触发写入磁盘的操作。
2、当设置该参数为 1 时,表示每次事务提交时,都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘,这样可以保证 MySQL 异常重启之后数据不会丢失。
3、当设置该参数为 2时,表示每次事务提交时,都只是缓存在 redo log buffer 里的 redo log 写到 redo log 文件,这并不意味着写入到了磁盘,而是写到了操作系统的Page Cache。

参数为1的时候会主动持久化到磁盘,但是0和2不会,那么这两个什么时候持久化到磁盘呢?

InnoDB 的后台线程每隔 1 秒:
(1)针对参数 0 :会把缓存在 redo log buffer 中的 redo log ,通过调用 write() 写到操作系统的 Page Cache,然后调用 fsync() 持久化到磁盘。所以参数为 0 的策略,MySQL 进程的崩溃会导致上一秒钟所有事务数据的丢失;
(2)针对参数 2 :调用 fsync,将缓存在操作系统中 Page Cache 里的 redo log 持久化到磁盘。所以参数为 2 的策略,较取值为 0 情况下更安全,因为 MySQL 进程的崩溃并不会丢失数据,只有在操作系统崩溃或者系统断电的情况下,上一秒钟所有事务数据才可能丢失。

我们可以通过系统变量来查看这个参数

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)

好了,redo log介绍完了,接着我们来介绍bin log的刷盘时机。

bin log的刷盘时机

每个线程有自己 binlog cache,最终会都写到同一个 binlog 文件。

binlog的刷盘过程:
(1) write,指的就是指把日志写入到 binlog 文件,但是并没有把数据持久化到磁盘,因为数据还缓存在文件系统的 page cache 里,write 的写入速度还是比较快的,因为不涉及磁盘 I/O。
(2)fsync,才是将数据持久化到磁盘的操作,这里就会涉及磁盘 I/O,所以频繁的 fsync 会导致磁盘的 I/O 升高。

那么什么时候刷盘呢?
通过sync_binlog 参数来控制数据库的 binlog 刷到磁盘上的频率:

1、sync_binlog = 0 的时候,表示每次提交事务都只 write,不 fsync,后续交由操作系统决定何时将数据持久化到磁盘;
2、sync_binlog = 1 的时候,表示每次提交事务都会 write,然后马上执行 fsync;
3、sync_binlog= N (N>1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才 fsync。

我们通过命令行来查看参数:

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

两次提交、组提交、双参数配合实现了两个日志的同步

有了前面两个刷盘时机,为什么还要有两次提交,因为我们需要保证redo log和bin log的一致性
两阶段提交的过程是如何的?
具体的取决于我们的参数,参数一共有四个分别如下所示:

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

其中,我们看到了两个新参数,他们是组提交参数:

1、 binlog_group_commit_sync_delay= N,表示在等待 N 微妙后,直接调用 fsync,将处于文件系统中 page cache 中的 binlog 刷盘,也就是将binlog 文件持久化到磁盘。表中值为1000000 (即1e6),就是1s。
2、 binlog_group_commit_sync_no_delay_count = N,表示如果队列中的事务数达到 N个,就忽视binlog_group_commit_sync_delay 的设置,直接调用 fsync,将处于文件系统中 page cache中的 binlog 刷盘。

不同的参数效果都是不一样的。

1、我们先来看最经典的双1配置
此刻事务提交时需要花费1.00 sec,因为binlog_group_commit_sync_delay设置的是1s,binlog_group_commit_sync_no_delay_count和binlog_group_commit_sync_delay满足其中一条即可

2、在双1的基础上,如果我们把innodb_flush_log_at_trx_commit改了呢?
每次redo log都没有刷盘,我们默认就成功了。

3、在双1的基础上,如果我们把sync_binlog改了呢?
此时事务提交只需要0.00sec,可以判定提交的瞬间未刷盘,但是提交成功了。因为sync_binlog=N,在后续的1~N-1的事务,commit都是很快,第N个事务commit所消耗的时间是1s左右。也就是在第N次时候,进行了刷盘。
这时候有人疑惑了,那么我的组提交参数有啥用?
我们来看结论:
开启两个并行的窗口,这两个窗口同时commit提交,并设置binlog_group_commit_sync_no_delay_count =2,我们发现刷盘了。 也就是说组提交在事务并行的时候才有效果。为什么要在并行事务的时候才有效果?

原来,早期的 MySQL 版本中,通过使用 prepare_commit_mutex 锁来保证事务提交的顺序,在一个事务获取到锁时才能进入
prepare 阶段,一直到 commit 阶段结束才能释放锁,下个事务才可以继续进行 prepare 操作。
通过加锁虽然完美地解决了顺序一致性的问题,但在并发量较大的时候,就会导致对锁的争用,性能不佳。

所以sync_binlog和组提交之间是相互配合而不是冲突矛盾的关系,在事务并发时组提交生效,而在没有并发时候,syc_binlog就发挥了巨大作用。

好了,关于日志刷盘的内容就到这了。

这篇关于MySQL日志——redo log和bin log的刷盘时机详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/863692

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)