必须了解的MySQL三种日志

文章已收录Github精选,欢迎Starhttps://github.com/yehongzhi/learningSummary

前言

大家有没有想过为什么MySQL数据库可以实现主从复制,实现持久化,实现回滚的呢?其实关键在于MySQL里的三种log,分别是:

  • binlog
  • redo log
  • undo log

这三种log也是面试经常会问的问题,下面我们一起来探讨一下吧。

一、binlog

binlog应该是日常中听的最多的关于mysql中的log。

那么什么是binlog呢?

binlog是用于记录数据库表结构和表数据变更的二进制日志,比如insert、update、delete、create、truncate等等操作,不会记录select、show操作,因为没有对数据本身发生变更。

binlog文件长什么样子呢?

使用mysqlbinlog命令可以查看。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-63Sik8eg-1616308429680)(https://static.lovebilibili.com/mysql_log_1.png)]

会记录下每条变更的sql语句,还有执行开始时间,结束时间,事务id等等信息。

如何查看binlog是否打开,如果没打开怎么设置?

使用命令show variables like '%log_bin%';查看binlog是否打开。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LtfAe1n5-1616308429685)(https://static.lovebilibili.com/mysql_log_2.png)]

如果像上图一样,没有开启binlog,那怎么开启呢?

找到my.cnf配置文件,增加下面配置(mysql版本5.7.31):

# 打开binlog
log-bin=mysql-bin
# 选择ROW(行)模式
binlog-format=ROW

修改后,重启mysql,配置生效。

执行SHOW MASTER STATUS;可以查看当前写入的binlog文件名。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PQsJEypo-1616308429689)(https://static.lovebilibili.com/mysql_log_3.png)]

binlog用来干嘛的呢?

第一,用于主从复制。一般在公司中做一主二从的结构时,就需要master节点打开binlog日志,从机订阅binlog日志的信息,因为binlog日志记录了数据库数据的变更,所以当master发生数据变更时,从机也能随着master节点的数据变更而变更,做到主从复制的效果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yQTCrUrO-1616308429694)(https://static.lovebilibili.com/mysql_log_5.jpg)]

第二,用于数据恢复。因为binlog记录了数据库的变更,所以可以用于数据恢复。我们看到上面图中有个字段叫Position,这个参数是用于记录binlog日志的指针。当我们需要恢复数据时,只要指定--start-position和--stop-position,或者指定--start-datetime和--stop-datetime,那么就可以恢复指定区间的数据。

二、redo log

假设有一条update语句:

UPDATE `user` SET `name`='刘德华' WHERE `id`='1';

我们想象一下mysql修改数据的步骤,肯定是先把id='1'的数据查出来,然后修改名称为'刘德华'。再深层一点,mysql是使用页作为存储结构,所以MySQL会先把这条记录所在的页加载到内存中,然后对记录进行修改。但是我们都知道mysql支持持久化,最终数据都是存在于磁盘中。

假设需要修改的数据加载到内存中,并且修改成功了,但是还没来得及刷到磁盘中,这时数据库宕机了,那么这次修改成功后的数据就丢失了。

为了避免出现这种问题,MySQL引入了redo log。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EuKjmzVF-1616308429698)(https://static.lovebilibili.com/mysql_log_4.png)]

如图所示,当执行数据变更操作时,首先把数据也加载到内存中,然后在内存中进行更新,更新完成后写入到redo log buffer中,然后由redo log buffer在写入到redo log file中。

redo log file记录着xxx页做了xxx修改,所以即使mysql发生宕机,也可以通过redo log进行数据恢复,也就是说在内存中更新成功后,即使没有刷新到磁盘中,但也不会因为宕机而导致数据丢失。

redo log与事务机制是如何配合工作的?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4lb936kS-1616308429699)(https://static.lovebilibili.com/mysql_log_7.png)]

如图所示:

第1-3步骤就是把数据变更,然后写入到内存中。

第4步记录到redo log中,然后把记录置为prepare(准备)状态。

第5,6步提交事务,提交事务之后,第7步把记录状态改成commit(提交)状态。

保证了事务与redo log的一致性。

binlog和redo log都可以数据恢复,有什么区别?

redo log是恢复在内存更新后,还没来得及刷到磁盘的数据。

binlog是存储所有数据变更的情况,理论上只要记录在binlog上的数据,都可以恢复。

举个例子,假如不小心整个数据库的数据被删除了,能使用redo log文件恢复数据吗

不可以使用redo log文件恢复,只能使用binlog文件恢复。因为redo log文件不会存储历史所有的数据的变更,当内存数据刷新到磁盘中,redo log的数据就失效了,也就是redo log文件内容是会被覆盖的。

binlog又是在什么时候记录的呢?

答,在提交事务的时候。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rTdT2Tkn-1616308429700)(https://static.lovebilibili.com/mysql_log_8.png)]

三、undo log

undo log的作用主要用于回滚,mysql数据库的事务的原子性就是通过undo log实现的。我们都知道原子性是指对数据库的一系列操作,要么全部成功,要么全部失败。

undo log主要存储的是数据的逻辑变化日志,比如说我们要insert一条数据,那么undo log就会生成一条对应的delete日志。简单点说,undo log记录的是数据修改之前的数据,因为需要支持回滚。

那么当需要回滚时,只需要利用undo log的日志就可以恢复到修改前的数据。

undo log另一个作用是实现多版本控制(MVCC),undo记录中包含了记录更改前的镜像,如果更改数据的事务未提交,对于隔离级别大于等于read commit的事务而言,不应该返回更改后数据,而应该返回老版本的数据

总结

学完之后,我们知道这三种日志在mysql中都有着重要的作用,再回顾一下:

  • binlog主要用于复制和数据恢复。
  • redo log用于恢复在内存更新后,还没来得及刷到磁盘的数据。
  • undo log用于实现回滚和多版本控制。

这篇文章就讲到这里了,感谢大家的阅读,希望看完大家能有所收获!
必须了解的MySQL三种日志

觉得有用就点个赞吧,你的点赞是我创作的最大动力~

我是一个努力让大家记住的程序员。我们下期再见!!!

能力有限,如果有什么错误或者不当之处,请大家批评指正,一起学习交流!
上一篇:shell编程之变量


下一篇:Discuz!的SEO优化策略二:如何去掉页脚多余的信息