欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL原理解读——redo log、undo log和binlog

程序员文章站 2022-07-08 14:23:47
...

MySQL原理解读——redo log、undo log和binlog


看似分散的多个概念,可以通过一套操作流程简单串起来,然后再逐步细讲

##1、两阶段提交

为了实现数据恢复,innodb采用两阶段提交,prepare和commiit

在一条写语句执行,到达存储引擎层时,会经过下面三个步骤:

  1. 将写操作缓存在Change Buffer中
  2. InnoDB记录undo log和redo log,MySQL进入prepare阶段
  3. 记录binlog,MySQL进入commit阶段

2、redo log(重做日志)

redo log属于innnodb存储引擎层

2.1、作用和来源

简单来说,redo log的作用有两个

  • 是为了在数据库异常宕机重启后,能恢复到宕机前的运行状态
  • 为了比较redo log中的checkpoint来刷脏

​ 由于InnoDB使用了Change Buffer提升写操作的性能,导致当数据库系统没有来的及刷新脏页而宕机时,会丢失Change Buffer中的写操作。为了解决这个问题,InnoDB在记录写操作到Change Buffer的同时,又记了一份到到Log Buffer中。在commit阶段会将Log Buffer中相关的写操作都持久化到磁盘磁盘文件,只有写操作成功持久化,commit才算成功。持久化的磁盘文件,就是我们提到的redo log

2.2、Log Buffer

​ 为了减少磁盘IO,InnoDB并不会将写操作马上持久化到磁盘,而是先记录到独立的缓存区中,达到了某个条件再持久化到磁盘,这个缓冲区就是Log Buffer。由于MySQL内存是用户态的,所以在Log Buffer持久化到磁盘之间的过程中,会先在系统内核态内存(OS Buffer)中转一下

Log Buffer刷入磁盘的时机有以下几个:

  • redo log buffer已经使用了一半的空间
  • 事务提交
  • 后台线程定时持久化
  • 数据库正常关闭

Log Buffer的持久化模式分为三种:

  • 0表示事务提交时只会将写操作写入Log Buffer,然后每秒定时将Log Buffer的写操作写入内核态内存,同时持久化到磁盘

  • 1表示事务提交时立刻将写操作写入Log Buffer,立刻写入内核态内存并立刻持久化到磁盘

  • 2表示事务提交时立刻将写操作写入Log Buffer,并立刻写入内核态内存,然后每秒定时将内核态内存中的写操作持久化到磁盘

可见1最具可靠性,而0和2效率更高,但是数据库异常宕机可能会丢失1秒的数据

查看当前Log Buffer的持久化模式,默认为模式1:

show variables like '%innodb_flush_log_at_trx_commit%'
Variable_name Value
innodb_flush_log_at_trx_commit 1

Log Buffer的定时持久化频率默认是1秒,但是也可以调:

show variables like '%innodb_flush_log_at_timeout%'
Variable_name Value
innodb_flush_log_at_timeout 1

Log Buffer占用的空间默认16M:

show variables like '%innodb_log_buffer_size%'
Variable_name Value
innodb_log_buffer_size 16777216

2.3、Log Group

redo log在磁盘上是以多个文件组合的形式存在的,类似于文件分块,我们把这组文件叫redo log group,默认文件个数为2:

show variables like '%innodb_log_files_in_group%'
Variable_name Value
innodb_log_files_in_group 2

redo log存在这里:

show variables like '%innodb_log_group_home_dir%'
Variable_name Value
innodb_log_group_home_dir ./

如果你查出来的路径跟我一样,说明redo log跟数据放在了一起。在datadir下会有ib_logfile0和ib_logfile1两个文件,这两个文件就是redo log,都存了InnoDB的写操作:

show variables like '%datadir%'
Variable_name Value
datadir /var/lib/mysql/

每个redo log file也有固定的大小,当一个redo log file被写满了,InnoDB会对另一个redo log file刷脏,并将Log Buffer写入这个redo log file可以理解为redo log group是多个redo log file首尾相连的环状队列,类似ring buffer。每个redo log file默认48M:

show variables like '%innodb_log_file_size%'
Variable_name Value
innodb_log_file_size 50331648

2.4、checkpoint

LSN(Log Sequence Number)又叫日志逻辑***,会随redo log的持久化而逐渐增大,记录在redo log file中和磁盘数据页中

redo log中的LSN我们也叫checkpoint,和最近一次刷的脏页的LSN相等,可以理解为,记录上一次刷脏的位置。

​ 数据库异常宕机重启后,会检查磁盘数据页最大的LSN,小于checkpoint说明change buffer中有写操作,也记了redo log,但是没有刷脏,就从redo log的checkpoint开始执行数据持久化,然后更新redo log file中的checkpoint

3、undo log(回滚日志)

undo log属于innodb存储引擎层

undo log的作用一共有两个:

  • 事务回滚
  • 多行版本控制(MVCC)

​ 当记录redo log的过程中,数据库异常宕机重启,恢复change buffer时所用到的redo log只记录了部分写操作,为了保证事务的原子性,使用undo log记录写操作的逆向日志,用来撤销写入redo log的不完整操作。

​ 当多个事务操作buffer pool中的同一条缓存数据。为保证乐观读,innodb在创建事务时生成活跃事务的快照,在提交写事务时记录对应的逆向逻辑,供其他读事务在提交时根据buffer pool中的实时数据和逆向逻辑计算出自己对应版本的数据。

undo log放在这里:

show variables like '%innodb_undo_directory%'
Variable_name Value
innodb_undo_directory ./

undo log默认最多存1G,但是只要没有使用它的事务,对应的undo log块就会被清掉:

show variables like '%innodb_max_undo_log_size%'
Variable_name Value
innodb_max_undo_log_size 1073741824
show variables like '%innodb_undo_log_truncate%'
Variable_name Value
innodb_undo_log_truncate ON

undo log表空间默认为2,最小值也为2,保证一个undo log file在truncate时还有一个undo log fiile可以使用:

show variables like '%innodb_undo_tablespaces%'
Variable_name Value
innodb_undo_tablespaces 2

4、binlog(归档日志)

binlog属于MySQL的Server层

binlog的作用只有一个,就是归档:binlog记录每一条sql,当数据库数据丢失时,可以根据binlog进行数据恢复

相关标签: 数据库