MySQL 三大日志:redo log,bin log,undo log

redo log

redo log 介绍

redo log(重做日志)是 InnoDB 存储引擎独有的,它用来保证 MySQL 的崩溃恢复能力。

当 MySQL 实例崩溃了,重启的时候,InnoDB 存储引擎就会使用 redo log 恢复数据,保证数据的持久性与完整性。

redo log 采用 WAL(Write-Ahead Logging)技术,即先写日志,再写磁盘。

当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log 里,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,这个更新往往是在系统比较空闲的时候做。

redo log 是物理日志,记录的是“在某个数据页上做了什么修改”,即修改后的结果;

redo log 文件

InnoDB 的 redo log 是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,即 redo log 总共就可以记录4GB的操作。从头开始写,写到末尾就又回到开头循环写。文件中包含两个指针 write pos 、checkpoint。

如下图所示:
在这里插入图片描述

redo log 是循环写的,空间固定会用完;

write pos 用来当前记录的位置,一边写一边后移,写到末尾后就回到文件开头。checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

write pos 和 checkpoint之间是 redo log 空着的部分,可以用来记录新的操作。如果 write pos 追上了 checkpoint,这时就表示 redo log 满了,这时候不能再执行新的更新,要先停下来先擦掉一些记录,把 checkpoint 推进一下。清除出一些空余空间,才可以继续写。

redo log 刷盘机制

事务在执行过程中,生成的 redo log 是要先写到 redo log buffer 的,然后 wirte 到 page cache,最后持久化到磁盘。

redo log 的刷盘策略与参数 innodb_flush_log_at_trx_commit 有关,可选择三种策略:

  • 0 :设置为 0 的时候,表示每次事务提交时不进行刷盘操作,每次事务提交时都只是把 redo log 留在 redo log buffer 中;
  • 1 :设置为 1 的时候,表示每次事务提交时都将redo log直接持久化到磁盘;(默认值)
  • 2 :设置为 2 的时候,表示每次事务提交时都只把 redo log buffer 内容写入 page cache

innodb_flush_log_at_trx_commit 参数默认为 1

另外,InnoDB 存储引擎有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的内容写到 page cache,然后调用 fsync 刷盘。

还有一种情况,当 redo log buffer 占用的空间即将达到 innodb_log_buffer_size 一半的时候,后台线程会主动刷盘。

另一种是,并行的事务提交的时候,顺带将这个事务的 redo log buffer 持久化到磁盘。假设一个事务 A 执行到一半,已经写了一些 redo log 到 redo log buffer 中,这时候有另外一个线程的事务 B 提交,如果 innodb_flush_log_at_trx_commit 设置的是 1,那么按照这个参数的逻辑,事务 B 要把 redo log buffer 里的日志全部持久化到磁盘。这时候,就会带上事务 A 在 redo log buffer 里的日志一起持久化到磁盘。

bin log

bin log 介绍

binlog 是 Server层 的日志,所有引擎都可以使用。

binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。

binlog是追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

bin log 格式

binlog 日志有三种格式,可以通过 binlog_format 参数指定。

  • statement:记录的内容是 SQL 语句原文
  • row:记录的内容不再是简单的 SQL 语句了,还包含操作的具体数据,比如语句中涉及了当前时间的情况,update t set time=now() where id=1,row 格式记录的内容看不到详细信息,要通过 mysqlbinlog 工具解析出来。但是这种格式需要更大的容量来记录,比较占用空间,恢复与同步时会更消耗 IO 资源,影响执行速度。
  • mixed:顾名思义,混合方式,MySQL 会判断这条 SQL 语句是否可能引起数据不一致,如果是,就用 row 格式,否则就用 statement 格式。

bin log 刷盘机制

事务提交的时候,执行器把 binlog cache 里的完整事务写入到 binlog 中,并清空 binlog cache。

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

这就涉及到两个操作:

  • write,指的就是指把日志写入到文件系统的page cache,并没有把数据持久化到磁盘,所以速度比较快。
  • fsync,才是将数据持久化到磁盘的操作。一般情况下,我们认为fsync才占磁盘的IOPS。

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

  • sync_binlog = 0 的时候,表示每次提交事务都只 write,不 fsync,由系统自行判断什么时候执行 fsync,如果主机崩溃,会丢失 page cache 里的 binlog 日志;
  • sync_binlog = 1 的时候,表示每次提交事务都会执行 fsync;
  • sync_binlog = N(N>1) 的时候,表示每次提交事务都write,但累积N个事务后才fsync。如果主机崩溃,会丢失最近N个事务的binlog日志。

undo log

如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行回滚,恢复机制就是通过 undo log 实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,直接利用 undo log 中的信息将数据回滚到修改之前的样子即可。并且,回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。

undo log 也是逻辑日志

undo log 的另一大应用就是 MVCC,MVCC 的实现依赖于:隐藏字段、Read View、undo log。在内部实现中,InnoDB 通过数据行的 DB_TRX_ID 和 Read View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 找到 undo log 中的历史版本。

参考资料

《MySQL 45 讲》

《JavaGuide》

《MySQL 必知必会》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值