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

2024-04-04 03:44

本文主要是介绍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/874714

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所