02.15 Day 27 - binlog 和 redo log 的写入机制

大家好,我是 Snow Hide,作为《MySQL 实战》这个专栏的学员之一,这是我打卡的第 27 天,也是我第 89 次进行这种操作。

今天我温习了该专栏里一篇叫《MySQL是怎么保证数据不丢的?》的文章。

关键词总结:binlog 的写入机制(write 和 fsync 的时机、通过sync_binlog 值来提升 IO 性能、sync_binlog 在实际业务场景中建议的值)、redo log 的写入机制(redo log 可能存在的三种状态、innodb_flush_log_at_trx_commit 参数的三种取值可能、没有提交事务的 redo log 写入磁盘的两种场景、innodb_flush_log_at_trx_commit 参数为 1 时、后台刷盘加崩溃恢复的组合、MySQL 的 “双 1” 配置、日志逻辑序列号(LSN,log sequence number)、写 binlog 的两步骤、提升 binlog 组提交的效果、WAL 机制得益于两方面、提升 IO 性能瓶颈的方法)。

所学总结:

binlog 的写入机制

  • 事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 binlog 文件中;
  • 一个事务的 binlog 无法拆开,不论是无大小,都要确保一次写入。涉及到 binlog cache 的保存问题;
  • 系统给 binlog cache 分配了一片内存,每个线程一个,参数 binlog_cache_size 用于控制单个线程内 binlog cache 所占内存的大小。超过参数规定的大小时要暂存至磁盘;
  • 事务提交时,执行器把 binlog cache 里的事务写入 binlog 中,并清空 binlog cache;
  • write 是指把日志写入文件系统的 page cache,并不把数据持久化至磁盘,所以速度比较快;
  • fsync 才是将数据持久化的操作。一般我们认为 fsync 才占磁盘的 IOPS。

write 和 fsync 的时机

  • sync_binlog=0 时,表示每次提交事务都只 write,不 fsync
  • sync_binlog=1 时,表示每次提交事务都会执行 fsync
  • sync_binlogN(N>1) 时,表示每次提交事务都 write,但累积 N 个事务后才 fsync

通过sync_binlog 值来提升 IO 性能

出现 IO 瓶颈时,将 sync_binlog 设置成一个比较大的值,可以提升性能。

sync_binlog 在实际业务场景中建议的值

考虑到丢失日志量的可控性,一般不建议将这个参数设成 0,比较常见的是将其设置为 100~1000 中的某个数值。
 

redo log 的写入机制

redo log 可能存在的三种状态

  • 存在 redo log buffer 中,物理上是在 MySQL 进程内存中;
  • 写到磁盘(write),但是没有持久化(fsync),物理上是在文件系统的 page cache 里;
  • 持久化到磁盘,对应的是 hard disk。

innodb_flush_log_at_trx_commit 参数的三种取值可能

  • 设置为 0 时,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中;
  • 设置为 1 时,表示每次事务提交时都将 redo log 直接持久化到磁盘;
  • 设置为 2 时,表示每次事务提交时都只是把 redo log 写到 page cache。

没有提交事务的 redo log 写入磁盘的两种场景

  • redo log buffer 占用的空间即将达到 innodb_log_buffer_size 一半的时候,后台线程会主动写盘;
  • 并行事务提交的时候,顺带将事务的 redo log buffer 持久化到磁盘。

innodb_flush_log_at_trx_commit 参数为 1 时

那 redo log 在 prepare 阶段就要持久化一次,因为有一个崩溃恢复逻辑是要依赖于 prepare 的 redo log,再加上 binlog 来一起完成的。

后台刷盘加崩溃恢复的组合

InnoDB 会认为 redo log 在 commit 时就不 fsync 了,只要 write 到文件系统的 page cahce 中足矣。

MySQL 的 “双 1” 配置

sync_binloginnodb_flush_log_at_trx_commit 都设置成 1 时。一个事务完整提交前,需要等待两次刷盘:redo log(prepare 阶段)、binlog。

日志逻辑序列号(LSN,log sequence number)

单调递增,用来对应 redo log 的一个个写入点。每次写入长度为 length 的 redo log,LSN 的值就会加上 length

写 binlog 的两步骤

  • 先把 binlog 从 binlog cache 中写入至磁盘的 binlog 文件;
  • 调用 fsync 持久化。

提升 binlog 组提交的效果

以下两个条件是或的关系,当其中一个满足条件时就会调用 fsync

  • binlog_group_commit_sync_delay 参数,表示延迟多少微妙后才调用 fsync;
  • binlog_group_commit_sync_no_delay_count 参数,表示累积多少次以后才调用 fsync。

WAL 机制得益于两方面

  • redo log 和 binlog 都是顺序写,磁盘的顺序写比随机写速度要快;
  • 组提交机制,可以大幅降低磁盘的 IOPS 消耗。

提升 IO 性能瓶颈的方法

  • 设置 binlog_group_commit_sync_delaybinlog_group_commit_sync_no_delay_count 参数,减少 binlog 的写盘次数。这个方法是基于 “额外的故意等待” 来实现的,因此可能会增加语句的响应时间,但没有丢失数据的风险;
  • sync_binlog 设置为大于 1 的值(比较常见的是 100~1000)。这样做的风险是,主机掉电时会丢 binlog 日志;
  • innodb_flush_log_at_trx_commit 设置为 2.这样的风险是,主机掉电时会丢数据。
     

末了

重新总结了一下文中提到的内容:怎么保证 redo log 和 binlog 是完整的、对 crash-safe 概念的清晰理解。

发布了151 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/stevenchen1989/article/details/104323024
今日推荐