Mysql中7种日志

【摘要】 前言
MySql更新流程如下,下面会一次介绍redo log、undo log以及binlog
Redo log(重做日志)
前面文章提到过缓存池以及刷页的操作,如果由于某种原因导致Mysql宕机还是还未来得及刷页的话则会导致数据丢失,未解决此问题,于是引入了redo log
它记录的是数据库中每个页的修改,而不是某一行或某几行修改成怎么样,可以用来恢复提交后的…

前言

MySql更新流程如下,下面会一次介绍redo log、undo log以及binlog在这里插入图片描述

Redo log(重做日志)

前面文章提到过缓存池以及刷页的操作,如果由于某种原因导致Mysql宕机还是还未来得及刷页的话则会导致数据丢失,未解决此问题,于是引入了redo log

它记录的是数据库中每个页的修改,而不是某一行或某几行修改成怎么样,可以用来恢复提交后的数据页,并且只能恢复至最后一次提交的位置。

在客户端尝试修改数据时,Innodb会把记录下写在redo log中,再修改缓存池中数据,当事务提交时,调用fsync把redo log刷入磁盘。至于缓存池的数据何时刷入磁盘由后台线程异步处理。

注意:此时redo log的事务状态是prepare,也就是未真正提交,要等bin log日志写入磁盘完成才变成commit,事务才算真正完成。所以当Mysql宕机后,只要重试解析redo log的更改记录进行重放、刷盘即可。

redo log重放(刷盘)过程

redo log采用固定大小,循环写入的方式。当redo log写满后从头开始写,形成一个环状。
因为redo log记录的是数据页上的修改,如果缓存池的数据页已经刷盘了,那redo log中记录的信息就失去了价值,那么新日志就可将这些失效记录进行擦除、覆盖。
在这里插入图片描述
上图中的write pos表示redo log当前记录的日志序列号(LSN),写入还未刷盘的记录,循环往后递增;check point表示redo log中的修改记录已经刷新到磁盘后的LSN,这个LSN之前的数据已经全部落盘;

write pos和check point之间的绿色部分表示空余部分,用来记录写的日志;check point到write pos之间是还未来得及刷盘的部分。当write pos追上check point时,就需要推动check point前移,即进行刷盘空出位置进行记录新的日志。

当redo log写满时,在擦除之前,需要确认这些要被擦除的数据对应内存中的数据页都已经全部落盘。并且擦除就记录腾出新空间这段期间是不能接受任何更新请求的,必然会导致Mysql性能下降。所以在高并发场景下,合理的调整redo log大小非常重要。

当Mysql启动时,无论上次是正常关闭还是异常退出,都会进行恢复操作,先检查数据页中的LSN,如果这个LSN小于redo log中的LSN(write pos位置),则说明redo log上存在未完成刷盘的记录,此时会从最近的check point出发开始同步数据。

在这里插入图片描述
如此数据页中LSN为300;redo log中LSN为500,则需要对redo log 中从LSN 300 -500的记录进行重放刷盘。

redo log写入机制

redo buffer以何种策略持久化到redo log可以通过innodb_flush_log_at_trx_commit进行设置
0:每秒提交 redo buffer -> os cache ->disk 可能丢失一秒内的事务数据
1(默认值):每次事务提交执行 redo buffer ->os cache ->disk 性能较差
2:每次事务提交 redo buffer->os cache ,然后由后台Master线程每隔1s进行刷盘

一般选择2这种模式,因为这种情况mysql挂了数据不会丢失,只有服务器挂了1秒才会丢失数据。

undo log(回滚日志)

undo log 也是 Mysql存储引擎InnoDB的事物日志,作用是起到回滚,保证了事务的原子性。记录的是数据修改前的状态,即在数据修改的流程中,记录一条与当前操作相反的回滚日志。
在这里插入图片描述
需要注意的是,假如一个事务中一条记录被多次修改,但是undo log只会记录原始版本的一条数据,每当对数据进行修改时,都会写入redo log。

作用

1.实现事务原子性,利用Undo log进行回滚
2.实现mvcc机制:undo log中保存了未提交之前版本数据,所以可以作为旧版本数据的快照以便其他事务进行读取

undo log负责完成回滚,redo log负责完成前滚

回滚

未提交的事务,即事务未执行commit。但是该事务内修改的脏页中,可能有一部分脏块已经刷盘。如果此时数据库宕机,则需要用回滚来将已经刷盘的脏块从磁盘上撤销

前滚

未完全提交的事务,即事务已经执行commit,但是缓存吃中的脏页还未来的急刷盘,此时数据库宕机就需要使用redo log进行前滚刷盘恢复数据

数据库重启时,先做前滚,后做回滚。可再看一下本文第一张图,可以看到redo log、undo log、bin log都是在刷脏页之前就已经刷到了磁盘上,这俄中互相协作才能保证用户提交的数据不会丢失。

bin log (归档日志)

bin log是数据库server层日志,和存储引擎无关,以二进制形式存储在磁盘中的逻辑日志,记录了所有DDL和DML操作(不包括select和show)。默认情况下是关闭的。bin log不会向redo log那样会擦出无用日志,而是永久存储(也可以设置过期时间,默认是永久保存),默认文件1G,超过此阈值会新建一个文件进行记录。主要作用于主从同步以及基于时间点的数据还原

主从同步

在这里插入图片描述
1.主库执行DDL和DML操作,按照修改顺序以此写入bin log.
2.从库的IO线程连接上主库并请求读取指定位置position的日志内容
3.主库收到请求后,将制定位置position之后的内容日志、主库bin log文件名称以及在日志中的位置推送给从库。
4.从库IO线程收到数据后,将日志内容以此写入relay log文件最末端,并将bin log文件名和位置position记录到master-info文件中,以遍下次使用。
5.从库的sql线程检测到relay log中内容更新后,读取日志并解析成可执行的sql语句进行主从同步。

其他功能

1.基于时间点恢复数据
2.通过订阅bin log可以做很多事情,比如同步上游数据、和redis配合实现延时双删等。

bin log文件记录模式

ROW STATEMENT MIXED
记录每一行数据被修改的情况 ,然后Slave端对相同的数据进行修改。优点:能清除记录每一行数据修改细节,能完全实现主从数据同步和数据恢复;缺点:批量操作会产生大量日志,尤其是alter table会让日志暴涨 每一条被修改的数据的sql会记录到master的bin log中,slave在复制的时候sql进程会解析成和原来master执行过的相同的sql再次执行,简称sql语句复制。优点:日志量小,减少磁盘IO,提升存储和恢复速度;缺点:在某些情况下会导致主从数据不一致,例如now()函数 以上两种模式混合使用,对于STATEMENT模式无法复制的使用ROW模式保存bin log,mysql会根据执行的sql自行选择写入模式
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享