暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL里的redo log和binlog

dejavuyj 2021-05-18
801

redo log

redo log是InnoDB引擎特有的日志类型,像MyISAM引擎就没有redo log.redo log记录物理日志,在某个数据页上做了什么修改.

redo log通过write pos和check point实现循环写.因此不能用来做归档(因为日志文件满了以后以前的日志会被覆盖掉)

write pos是redo log的当前写位置, check point记录刷脏页的位置.

内存数据页和磁盘数据页内容不一致时,这个内存页就是"脏页".而当redo log写满了,就要刷掉一部分脏页,把check point往前移.



redo log的写入机制

redo log的三种状态:

  1. 存在redo log buffer中,物理上是在MySQL进程内存中

  2. 写到磁盘(write),但是没有持久化(fsync),物理上是在文件系统的page cache里

  3. 持久化到磁盘, 对应的是hard disk

innodb_flush_log_at_trx_commit的取值:

  • 设置为0 每次事务提交都只把redo log留在redo log buffer中

  • 设置为1 每次事务提交都将redo log直接持久化到磁盘

  • 设置为2 每次事务提交都只把redo log写到page cache

InnoDB有个后台线程,每个1秒会把redo log buffer中的日志调用wrute写到文件系统的page cache, 然后调用fsync持久化到磁盘


InnoDB通过LSN实现组提交机制来提升系统性能.

有两个参数可以放大组提交机制的效果:


binlog_group_commit_sync_delay参数表示延迟多少微秒后才调用fsync

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. 把innodb_flush_log_at_trx_commit设置为2,风险是主机掉电会丢失数据


binlog

MySQL里的binlog是在server层实现,所有存储引擎都能使用.

binlog保存的是逻辑日志,记录语句的原始逻辑,例如一个sql语句.

binlog采用追加写的方式来进行写入,不会像redo log那样覆盖掉之前的日志.

它一开始是设计用来做归档的,当然主从同步时也会使用到binlog.


binlog的写入机制

首先,一个事务的binlog是不能被拆分的,因为要保持事务的原子性.

在事务执行过程中,把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中.

系统给每个线程分配一块binlog cache内存,如果超过binlog_cache_size的大小,就要暂存到磁盘中.


       


图中write是指把日志写入到文件系统的page cache,这时并没有持久化到磁盘,所以速度比较快.

fsync才把数据持久化到磁盘,fsync会占用磁盘的IOPS.

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

  1. sync_binlog=0 每次提交事务只write, 不fsync

  2. sync_binlog=1 每次提交事务都执行fsync

  3. sync_binlog=N 每次提交事务都write, 但累积N个事务后才fsync

出现IO瓶颈的场景,将sync_binlog设置成一个比较大的值,可以提升性能,比较常见的是设置为100-1000中的某个数值.风险是如果主机发生异常重启,会丢失最近N个事务的binlog日志


binlog有以下三种格式:

  • statement binlog里记录SQL语句的原文,可能会造成主备不一致(delete limit 主备用不同的索引就会造成删掉的数据不一致)

  • row binlog里记录真实删除行的主键id,不会出现主备不一致的情况, 但是占用空间比较大, 写binlog也会耗费更多IO资源

  • mixed MySQL自己判断这条SQL语句是否可能引起主备不一致,如果有可能,就用row格式,否则用statement格式.


两阶段提交

MySQL使用两阶段提交来保证两个redo log和binlog的数据一致性


InnoDB写redo log,处于prepare阶段

server层写binlog

InnoDB提交事务,处于commit状态

通过两阶段提交来保证redo log和binlog的状态保持逻辑上一致.
而数据恢复,搭建新备库都需要数据文件和日志文件保持逻辑上的一致性.


参考文献

极客时间专栏 - MySQL实战45讲

文章转载自dejavuyj,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论