MySQL binlog和redolog的写入机制

binlog的写入机制

每个线程都会先将日志写入到binglog cache, 事务提交的时候,再把binlog cache写到binlog文件中。所有线程都写一个binlog日志。

binlog_cache_size 用于控制单个线程内binlog cache 所占内存的大小,如果超过了这个参数规定的大小,就要暂存到磁盘。

write 和 fsync 的时机,是由参数 sync_binlog 控制的:

  1. sync_binlog=0 的时候,表示每次提交事务都只 write,不 fsync;
  2. sync_binlog=1 的时候,表示每次提交事务都会执行 fsync;
  3. sync_binlog=N(N>1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才 fsync。

因此,在出现 IO 瓶颈的场景里,将 sync_binlog 设置成一个比较大的值,可以提升性能。在实际的业务场景中,考虑到丢失日志量的可控性,一般不建议将这个参数设成 0,比较常见的是将其设置为 100~1000 中的某个数值。

redo log 的写入机制

redo log 也是写入缓存,redo log buffer 之中。

redo log 事务提交时是否fsync,由参数innodb_flush_log_at_trx_commit控制:

  1. 为0的时候,不做任何操作。redo log还是在redo log buffer之中。
  2. 为1的时候,每次提交事务就把redo log buffer fsync到磁盘
  3. 为2的时候,只是把redo log 写到page cache

此外,innodb 后台线程会每隔1秒将 redo log buffer中的日志,写入文件系统的page cache,然后调用fsync持久化到磁盘。因此,一个还没提交的事务,其在redo log buffer中的redo log会被后台线程持久化。

还有两种情况,redo log buffer会持久化

  1. redo log buffer大小占用达到innodb_log_buffer_size 一半,后台线程主动写盘。事务没有提交,只是写道page cache
  2. 当设置innodb_flush_log_at_trx_commit, 其他事务提交了,顺带将redo log buffer中的提交了

组提交机制

redo log 是有序号的,(log sequence number, LSN), 组提交机制指的时, 序号大的事务提交后,可以保证小于等于这个需要的redo log 都持久化到磁盘了。

(trx1, trx2, trx3) 这一组事务,trx3 提交了,调用fsync可以将之前的都持久化到磁盘。

binlog 也可以通过参数设置组提交的效果

如果你想提升 binlog 组提交的效果,可以通过设置 binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 来实现。

  1. binlog_group_commit_sync_delay 参数,表示延迟多少微秒后才调用 fsync;
  2. binlog_group_commit_sync_no_delay_count 参数,表示累积多少次以后才调用 fsync。

如果你的 MySQL 现在出现了性能瓶颈,而且瓶颈在 IO 上,可以通过哪些方法来提升性能呢?针对这个问题,可以考虑以下三种方法:

  1. 设置 binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 参数,减少 binlog 的写盘次数。这个方法是基于“额外的故意等待”来实现的,因此可能会增加语句的响应时间,但没有丢失数据的风险。
  2. 将 sync_binlog 设置为大于 1 的值(比较常见是 100~1000)。这样做的风险是,主机掉电时会丢 binlog 日志。
  3. 将 innodb_flush_log_at_trx_commit 设置为 2。这样做的风险是,主机掉电的时候会丢数据
posted @ 2022-03-16 23:24  yihailin  阅读(498)  评论(0编辑  收藏  举报