0
点赞
收藏
分享

微信扫一扫

MySQL实战:三种日志都有啥用?

1kesou 2022-08-09 阅读 105


MySQL实战:三种日志都有啥用?_数据

rodolog:系统宕机了,如何避免数据丢失?

在前面的章节中我们引出了脏页这个概念,如果对应的脏页还没有被刷到磁盘中,数据库就宕机了,那我们的更改不久丢失了?

为了解决这个问题,我们需要把内存所做的修改写入到 redo log buffer中,这是内存里的一个缓冲区,用来存在redo日志。

rodo log记录了你对数据所做的修改,如“将id=1这条数据的name从a变为abc”,物理日志哈,后面会再提一下。

redo log是顺序写所以比随机写效率高

InnoDB的redo log是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么总大小为4GB。从头开始写,写到末尾就又回到开头循环写,如下面这个图所示。

MySQL实战:三种日志都有啥用?_提交事务_02


write pos是当前要写的位置,checkpoint是要擦除的位置,擦除前要把对应的脏页刷回到磁盘中。write pos和checkpoint中间的位置是可以写的位置。

当我们的系统能支持的并发比较低时,可以看看对应的redo log是不是设置的太小了。太小的话会导致频繁的刷脏页,影响并发,可以通过工具监控redo log的大小

redolog的大小 = innodb_log_file_size * innodb_log_files_in_group(默认为2)

MySQL实战:三种日志都有啥用?_提交事务_03


接下来我们详细聊聊,redolog是如何避免数据丢失的

事务未提交,MySQL宕机,这种情况Buffer Pool中的数据丢失,并且redo log buffer中的日志也会丢失,不会影响数据

提交事务成功,redo log buffer中的数据没有刷到磁盘,此时会导致事务提交的数据丢失。

鉴于这种情况,我们可以通过设置innodb_flush_log_at_trx_commit来决定redo log的刷盘策略

查看innodb_flush_log_at_trx_commit的配置

SHOW GLOBAL VARIABLES LIKE 'innodb_flush_log_at_trx_commit'

innodb_flush_log_at_trx_commit值

作用

0

提交事务时,不会将redo log buffer中的数据写入os buffer,而是每秒写入os buffer并刷到磁盘

1

提交事务时,必须把redo log从内存刷入到磁盘文件中

2

提交事务时,将rodo log写入os buffer中,默认每隔1s将os buffer中的数据刷入磁盘

应为0和2都可能会造成事务更新丢失,所以一般系统中innodb_flush_log_at_trx_commit的值都为1,你可以看看你们的系统用的哪个值?

undolog:如何让更新的数据可以回滚?

当执行更改操作时,比如id=1的记录的name从王昭君改为西施,会把原来的记录写入到undo log中。当事务回滚时,就可以通过undolog将数据恢复为原来的模样。

MySQL实战:三种日志都有啥用?_mysql_04


此外,undo log在mvcc的实现中也扮演了重要的作用

binlog:主从库之间如何同步数据?

当我们把mysql主库的数据同步到从库,或者其他数据源时,如es,bi库时,只需要订阅主库的binlog即可。

MySQL实战:三种日志都有啥用?_mysql_05


为什么要弄2种日志呢?

其实这都是由历史原因决定的

MySQL刚开始用binlog实现归档的功能,但是binlog没有crash-safe的能力,所以后来InnoDB引擎加了redo log来实现crash-safe。假如MySQL中只有一个InnoDB引擎,说不定就能用redo log来实现归档了,此时就可以将redo log和 binlog合并到一块了

这两种日志的区别如下:

  1. redo log是InnoDB存储引擎特有,binglog是MySQL的server层实现的,所有引擎都可以使用
  2. redo log是物理日志,记录的是数据页上的修改。binlog是逻辑日志,记录的是语句的原始逻辑,如给id=2的这一行的c字段加1
  3. redo log是固定空间,循环写。binlog是追加写,当binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志

我们可以通过设置sync_binlog来决定binlog的刷盘策略

sync_binlog值

作用

0

不立即刷盘,将binlog写入os buffer,由操作系统决定何时刷盘 ,有可能会丢失多个事务的数据

1

将binlog写入os buffer,每n个事务提交后,将os buffer的数据刷盘

一般情况下将sync_binlog的值设为1即可

两阶段提交

接着我们来看一下将id=2的行c字段加1的执行流程。

MySQL实战:三种日志都有啥用?_提交事务_06


前面的这个阶段大家应该都能看懂了把,没看懂的可以看一下《MySQL实战45讲

》,重点说一下最后三个阶段

  1. 引擎将新数据更新到内存中,将操作记录到redo log中,此时redo log处于prepare状态,然后告知执行器执行完成了,可以提交事务
  2. 执行器生成操作的binlog,并把binlog写入磁盘
  3. 引擎将写入的redo log改为提交状态,更新完成

为什么要把relog的写入拆成2个步骤?即prepare和commit,两阶段提交

因为不管你先写redolog还是binlog,奔溃发生后,最终其实都有可能会造成原库和用日志恢复出来的库不一致

而两阶段提交可以避免这个问题

redolog和binlog具有关联行,在恢复数据时,redolog用于恢复主机故障时的未更新的物理数据,binlog用于备份操作。每个阶段的log操作都是记录在磁盘的,在恢复数据时,redolog 状态为commit则说明binlog也成功,直接恢复数据;如果redolog是prepare,则需要查询对应的binlog事务是否成功,决定是回滚还是执行。

MySQL实战:三种日志都有啥用?_数据_07

举报

相关推荐

0 条评论