Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • MySQL

    • 基础部分

      • 初识MySQL
      • 基础架构&日志
      • 事务隔离
      • 全局锁、表锁、行锁
      • 事务的隔离性和行锁
      • 索引
      • 索引深入(中)
      • 内存脏页刷盘
      • 数据库表的空间回收
      • count
      • order by
      • SQL语句性能差异分析
      • 幻读与间隙锁
      • 加锁规则案例分析
      • binlog和redolog如何写入磁盘
        • binlog写入机制
        • redolog写入机制
        • 组提交机制
        • MySQL针对组提交的延迟持久化
        • 磁盘IO瓶颈问题解决方案
        • “非双1”设置的场景
      • MySQL一致性与高可用性
      • kill命令
      • 全表扫描与内存占用
      • join
      • 临时表与内存表
      • 自增主键
      • insert操作加锁场景分析
      • grant
      • 分区表
      • 思维导图
    • 实战与处理方案

    • 面试

  • ORM框架

  • 数据库
  • MySQL
  • 基础部分
phan
2023-06-30
目录

binlog和redolog如何写入磁盘

# binlog和redolog如何写入磁盘

# binlog写入机制

binlog cache:事务会把日志写到内存里的binlog cache,作为缓冲区。每个线程单独持有一份cache内存空间。

binlog_cache_size:单个线程内binlog cache占用内存的大小。如果事务的日志超过这个阈值会暂存到磁盘。

每个线程事务都会有自己一块binlog cache,而所有线程共用同一份binlog file。

整个binlog写磁盘分为两个过程:

  • write:指的是每个线程将自己的日志写入到文件系统的page cache,并没有把数据持久化到磁盘,因此这一步速度比较快,
  • fsync:真正将数据同步持久化到磁盘上。这一步占用磁盘的IOPS。

具体这两个步骤的执行时机,是通过sync_binlog参数控制:

  • sync_binlog=0:表示每次事务提交只write,不会fsync;
  • sync_binlog=1:表示每次事务提交都会执行write和fsync
  • sync_binlog=N(N>1):每次事务提交都会write,只有当binlog files积累了N个事务的日志后,才会执行fsync持久化到磁盘。

💡实际场景中,一般sync_binlog设置为100~1000中的某个值,因为fsync是比较耗时吃性能的,设置日志分批持久化的阈值可以有效提高整个数据库的性能。当然这种方法如果数据库异常重启或者宕机之后,这N个事务的日志不能恢复。

# redolog写入机制

redolog buffer:在MySQL服务端,所有线程共用一个内存的redolog buffer,不同事务的日志都会写到这个区域。由于两阶段提交机制,buffer中的日志生成后只要没有持久化到磁盘,即使丢失了也没有关系。

与binlog类似,整个redolog日志可能存在三种状态:

  • 存在MySQL内存的redolog buffer中
  • write写到磁盘文件系统的page cache(本质是文件系统向内核申请的一块内存),但是还没有fsync持久化。
  • fsync持久化到磁盘hard dist。这一步骤最影响数据库性能,写到磁盘速度比较慢。

具体redolog日志的写入策略,通过innodb_flush_log_at_trx_commit参数控制:

  • innodb_flush_log_at_trx_commit=0:每次事务提交都只是将redolog留在内存redolog buffer
  • innodb_flush_log_at_trx_commit=1:每次事务提交都将日志fsync持久化到磁盘中
  • innodb_flush_log_at_trx_commit=2:每次事务提交只把redolog写到page cache(主机断电会丢失,但是MySQL重启不会丢失)。

上面讲了内存中的redolog可以丢失,只要有两阶段提交协议和事务保证一致性即可。实际上即使当前事务没有提交,在下面这几种场景下,内存redolog buffer中的日志也可能已经持久化到磁盘当中。

  1. InnoDB有一个后台线程,每隔一秒的轮询机制就会将redolog buffer中的日志先write再fsync持久化到磁盘。
  2. 内存redolog buffer的日志文件大小如果达到innodb_log_buffer_size的一半,那么后台线程会主动写到磁盘的page cache。
  3. 其它并行事务B在进行提交后,即使当前事务A还没执行完,也会连带将整个redolog buffer日志一并提交。

注意这里如果innodb_flush_log_at_trx_commit=1,那么一阶段redolog更改为prepare时,就需要持久化一次,因为这里存在一种崩溃恢复的情况,需要根据redolog和binlog状态和完整性来恢复。而最后commit后redolog只需要write到page cache就足够了。

“双1配置”:sync_binlog和innodb_flush_log_at_trx_commit都设置为1,一个事务从开始到提交等待两次刷盘:①redolog(prepare)②binlog

# 组提交机制

日志逻辑序列号LSN (log sequence number):对应redolog的写入点,在LSN写入length长度的日志文件后,下一个LSN就会更新为LSN+length。注意leader在开始写盘之前,每进来一个事务LSN都会增加。

  1. trx1第一个到达,会作为本组的leader
  2. trx1写日志之前,组里总共进来了三个事务,LSN为160
  3. trx1进行写盘时带着LSN=160进行持久化,也就是上面的场景3,它会连带trx2和trx3的日志一并持久化
  4. 整个组内所有LSN小于160的redolog最终都会被持久化。

并发场景下,一个组内的事务越多,准备阶段redolog的fsync越晚,那么节约磁盘IOPS效果越好。

# MySQL针对组提交的延迟持久化

两阶段提交①写入redolog(prepare阶段)②写binlog③提交事务redolog提交状态。根据上述两个日志文件的写盘流程,并且经过MySQL优化流程后,原先的两阶段提交可以进一步细化为如下状态:

  • 将处于prepare状态的redolog的fsync刷盘流程延迟放到第三步进行,从而使组提交节省更多的IOPS。
  • 步骤4binlog进行刷盘时也可以进行组提交(因为binlog files也是所有事务共享的),但步骤3执行速度比较快,组提交效果通常不如redolog
  • 要想提升binlog组提交效果,可以通过设置binlog_group_commit_sync_delay和binlog_group_commit_sync_no_delay_count实现

binlog_group_commit_sync_delay:表示延后多少微妙后才调用fsync

binlog_group_commit_sync_no_delay_count:表示累计多少次后才调用fsync。N个事务后提交才返回给客户端,也就是说客户端只要能拿到,那么一定是持久化过的。

# 磁盘IO瓶颈问题解决方案

  • 方案一、设置binlog_group_commit_sync_delay和binlog_group_commit_sync_no_delay_count两个参数,延长刷盘的时机,减少磁盘IO次数。

    缺点:可能会延长SQL语句的i响应时间

  • 方案二、设置sync_binlog改为大于1,分组刷盘提交

    缺点:数据库宕机可能会导致内存中N个事务日志的丢失

  • 方案三、设置innodb_flush_log_at_trx_commit为0,将redolog写到文件系统的page cache

    缺点:主机断电丢失redolog

# “非双1”设置的场景

显然在“双1”设置下,事务每次提交都会马上直接持久化binlog和redolog,高并发场景下磁盘读写次数增加,消耗IOPS,从而导致增加数据库的写盘压力。因此在以下场景,需要设置成“非双1”配置:innodb_flush_logs_at_trx_commit=2、sync_binlog=1000

  • 业务高峰期。如果有可以预知的业务高峰期,DBA需要将主库设置成”非双1“
  • 备库延迟。主从模式下,如果备库设置双1,会导致主库还没有持久化,备库就已经完成持久化并将日志更新成最新了。当备库追上主库后再改回来。
  • 用备份恢复主库的副本,应用binlog的过程。
  • 批量导入数据的时候。
编辑 (opens new window)
#数据库
上次更新: 2023/12/15, 15:49:57
加锁规则案例分析
MySQL一致性与高可用性

← 加锁规则案例分析 MySQL一致性与高可用性→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式