MySQL原理解读——redo log、undo log和binlog
MySQL原理解读——redo log、undo log和binlog
看似分散的多个概念,可以通过一套操作流程简单串起来,然后再逐步细讲
##1、两阶段提交
为了实现数据恢复,innodb采用两阶段提交,prepare和commiit
在一条写语句执行,到达存储引擎层时,会经过下面三个步骤:
- 将写操作缓存在Change Buffer中
- InnoDB记录undo log和redo log,MySQL进入prepare阶段
- 记录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进行数据恢复
上一篇: MySQL redo log
推荐阅读
-
MySQL的日志(二):事务日志(redo log和undo log)
-
MySQL 日志系统之 redo log 和 binlog
-
MySQL的日志(二):事务日志(redo log和undo log)
-
MySQL 重要参数 innodb_flush_log_at_trx_commit 和 sync_binlog
-
数据库——MySQL日志(redo log、undo log、bin log、erro log、slow query log、general log)
-
Mysql redo、undo、bin、relay log 区别
-
mysql 事务日志 redo log和undo log
-
MySQL之Undo Log和Redo Log
-
【MySQL】之 binlog、undo log 和 redo log 详解
-
MySQL原理解读——redo log、undo log和binlog