查看原文
其他

关于MySQL日志,我与阿里P9都聊了些啥?

冰河 冰河技术 2022-09-10

点击上方蓝色“冰河技术”,关注并选择“设为星标”

持之以恒,贵在坚持,每天进步一点点!



作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:

https://github.com/sunshinelyz/mykit-delay

PS: 欢迎各位Star源码,也可以pr你牛逼哄哄的代码      

写在前面

周末,我与阿里P9资深技术专家(这里就不说名字了),聊起了MySQL这个话题,为啥会聊这个呢?因为他看到我出版了一部《MySQL技术大全:开发、优化与运维实战》,对书籍的评价也是不错的。随后,我们聊了关于MySQL的几个话题,其中一个就是MySQL的日志机制。今天,我就把大概聊的一些内容以书面文章的形式分享给大家。希望能够为小伙伴们带来实质性的帮助!

文章已收录到:

https://github.com/sunshinelyz/technology-binghe

https://gitee.com/binghe001/technology-binghe

MySQL日志

说起MySQL的日志,有三种类型的日志对于MySQL来说是至关重要的,这三种日志分别为:Binlog、Undo Log 和 Redo Log。

由于Binlog和UndoLog有类似的地方,所以,我们按照如下顺序依次介绍MySQL中的三大日志原理:Undo Log——> Redo Log ——> Binlog。

Undo Log日志

什么是Undo Log

顾名思义,Undo Log的字面意思就是撤销操作的日志,指的是使MySQL中的数据回到某个状态。

在MySQL数据库中,事务开始之前,MySQL会将待修改的记录保存到Undo Log中,如果数据库崩溃或者事务需要回滚时,MySQL可以通过利用Undo Log日志,将数据库中的数据回滚到之前的状态。

MySQL新增、修改和删除数据时,在事务开始前,就会将信息写入Undo Log中。事务提交时,并不会立刻删除Undo Log, InnoDB存储引擎会将事务对应的Undo Log放入待删除列表中,之后会通过后台的purge thread对待删除的列表进行删除处理。这里,值得注意的是:Undo Log是一种 逻辑日志, 记录的是一个变化过程。比如,MySQL执行一个delete操作,Undo Log就会记录一个insert操作;MySQL执行一个insert操作,Undo Log就会记录一个delete操作;MySQL执行一个update操作,Undo Log就会记录一个相反的update操作。

Undo Log以段的方式来管理和记录日志信息,在InnoDB存储引擎的数据文件中,包含了一种叫做rollback segment的回滚段,其内部包含了1024个undo log senment。

Undo Log作用

Undo Log对于MySQL实现事务来说,起着至关重要的作用,它实现了事务的原子性和多版本并发控制,也就是我们经常说的MVCC。

  • 实现事务的原子性

Undo Log能够实现MySQL事务的原子性,在事务的处理过程中,如果MySQL出现了错误或者用户手动执行了事务的回滚操作(执行了rollback操作),MySQL可以利用Undo Log日志将数据库中的数据恢复到之前的状态。

  • 实现MVCC机制

Undo Log在MySQL的InnoDB存储引擎中实现了多版本并发控制(MVCC)机制。事务未提交前,Undo Log保存了未提交之前的版本数据,Undo Log中的数据可以作为旧版本数据的副本或者快照以便其他并发事务进行读取操作。

事务A手动开启事务后,对goods数据表中id为1的数据进行更新操作,首先会把更新命中的数据写入到Undo Buffer中。在事务A未提交之前,此时,事务B手动开启事务,对goods数据表中的id为1的数据进行查询操作,此时的事务B会读取Undo Log中的数据并返回给客户端,这就是MySQL中的MVCC机制。

可以在MySQL中通过下面的命令来查看控制Undo Log日志的参数。

show variables like '%innodb_undo%';

Redo Log日志

说了MySQL中的Undo Log,我们再来看看MySQL中的Redo Log日志。

什么是Redo Log

顾名思义Redo Log的字面意思就是重做日志,指的是在数据库出现意外情况时能够对重新执行某种操作。在MySQL中,事务中修改的任何数据,都会将最新的数据写入Redo Log中进行备份。

在MySQL中,随着事务操作的执行,就会产生Redo Log日志,在事务提交时会产生Redo Log并将其写入Redo Buffer,Redo Buffer也并不是随着事务的提交就会被立刻写入到磁盘中,而是等事务操作的脏页写入到磁盘之后,Redo Log的使命也就完成了,此时,Redo Log日志占用的空间可以重新利用,会被后续产生的Redo Log日志覆盖。

Redo Log的原理

Redo Log 能够实现事务的持久性,防止在发生故障的时间点,有脏页未写入表的 ibd 文件中,在重启 MySQL 服务的时候,根据 Redo Log 进行重做,从而将未提交的事务进行持久化。这个过程可以简化为下图所示。

Redo Log的写机制

Redo Log文件的内容是以顺序循环的方式写入文件的,写满时就会回到第一个文件,进行覆盖写。

  • Write Pos 是当前记录的位置,一边写一边后移,写到最后一个文件末尾后就回到 0 号文件开头;
  • CheckPoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数 据文件;

Write Pos 和 CheckPoint之间还空着的部分,可以用来记录新的操作。如果 Write Pos 追上 CheckPoint,表示已经写满,此时就需要向后移动CheckPoint来擦除数据。

每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组至少有2个重做日志文件,默认为ib_logfile0和ib_logfile1 。

可以在MySQL中通过如下命令来查看控制Redo Log的参数。

show variables like '%innodb_log%';

Redo Log写入机制

在Redo Log日志信息从Redo Buffer持久化到Redo Log时,具体的持久化策略可以通过innodb_flush_log_at_trx_commit 参数进行设置,具体策略如下所示。

  • 0:每秒提交 Redo buffer ->OS cache -> flush cache to disk,可能丢失一秒内的事务数据。由后台Master线程每隔 1秒执行一次操作。
  • 1(默认值):每次事务提交执行 Redo Buffer -> OS cache -> flush cache to disk,这种方式最安全,性能最差。
  • 2:每次事务提交执行 Redo Buffer -> OS cache,然后由后台Master线程再每隔1秒执行OS cache -> flush cache to disk 的操作。

一般建议选择取值2,因为 MySQL 挂了数据没有损失,整个服务器挂了才会损失1秒的事务提交数据。

Binlog日志

什么是Binlog

Binlog记录所有MySQL数据库表结构变更以及表数据修改的二进制日志,不会记录select和show这类查询操作的日志。Binlog日志是以事件形式记录,还包含语句所执行的消耗时间。开启Binlog日志有以下两个最重要的使用场景。

  • 主从复制:在主库中开启Binlog功能,这样主库就可以把Binlog传递给从库,从库拿到Binlog后实现数据恢复达到主从数据一致性。
  • 数据恢复:通过mysqlbinlog等工具来恢复数据

关于Binlog的使用场景可以参见我出版的图书《MySQL技术大全:开发、优化和运维实战》一书。

Binlog文件记录模式

Binlog文件记录模式有STATEMENT、ROW和MIXED三种,具体含义如下。

ROW模式

ROW(row-based replication, RBR):日志中会记录每一行数据被修改的情况,然后在slave端对相同的数据进行修改。

优点:能清楚记录每一个行数据的修改细节,能完全实现主从数据同步和数据的恢复。

缺点:批量操作,会产生大量的日志,尤其是alter table会让日志暴涨。

STATMENT模式

STATMENT(statement-based replication, SBR):每一条被修改数据的SQL都会记录到master的Binlog中,slave在复制的时候SQL进程会解析成和原来master端执行过的相同的SQL再次执行。简称SQL语句复制。

优点:日志量小,减少磁盘IO,提升存储和恢复速度

缺点:在某些情况下会导致主从数据不一致,比如last_insert_id()、now()等函数。

MIXED模式

MIXED(mixed-based replication, MBR):以上两种模式的混合使用,一般会使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择写入模式 。

Binlog文件结构

对于MySQL的Binlog文件结构有三种版本,见下图。

关于Binlog文件结构的具体信息,小伙伴们可以参考MySQL的官方文档,具体链接为:https://dev.mysql.com/doc/internals/en/event-header-fields.html

Binlog写机制

根据记录模式和操作触发event事件生成log event(事件触发执行机制)。

将事务执行过程中产生的日志时间(log event)写入缓冲区,每个事务线程都有一个缓冲区。Log Event保存在一个binlog_cache_mngr数据结构中,在该结构中有两个缓冲区,一个是stmt_cache,用于存放不支持事务的信息;另一个是trx_cache,用于存放支持事务的信息。

事务在提交阶段会将产生的log event写入到外部binlog文件中。不同事务以串行方式将log event写入Binlog文件中,所以一个事务包含的log event信息在binlog文件中是连续的,中间不会插入其他事务的log event。

Binlog文件操作

Binlog状态查看

show variables like 'log_bin';

开启Binlog功能,需要修改my.cnf或my.ini配置文件,在[mysqld]下面增加log_bin=mysql_bin_log,重启 MySQL服务。

binlog-format=ROW
log-bin=mysqlbinlog

使用show binlog events命令

show binary logs; //等价于show master logs;
show master status;
show binlog events;
show binlog events in 'mysqlbinlog.000001';

使用mysqlbinlog 命令

mysqlbinlog "文件名"
mysqlbinlog "文件名" > "test.sql"

使用 binlog 恢复数据

//按指定时间恢复
mysqlbinlog --start-datetime="2021-02-28 18:00:00" --stopdatetime="2021-03-01 00:00:00" mysqlbinlog.000001 | mysql -uroot -p123456
//按事件位置号恢复
mysqlbinlog --start-position=1789 --stop-position=2674 mysqlbinlog.000001
| mysql -uroot -p123456

删除Binlog文件

purge binary logs to 'mysqlbinlog.000001'; //删除指定文件
purge binary logs before '2021-03-01 00:00:00'; //删除指定时间之前的文件
reset master; //清除所有文件

可以通过设置expire_logs_days参数来启动自动清理功能。默认值为0表示没启用。设置为大于0的整数表示超出多少天binlog文件会自动清除。

更多有关于Binlog日志的信息,可以参考我出版的《MySQL技术大全:开发、优化与运维实战》一书。

最后,如果小伙伴们想购买《MySQL技术大全:开发、优化与运维实战》一书,可通过如下小程序链接购买哦!

好了,今天就到这儿吧,我是冰河,大家有啥问题可以在下方留言,也可以加我微信:sun_shine_lyz,我拉你进群,一起交流技术,一起进阶,一起牛逼~~

冰河原创PDF

关注 冰河技术 微信公众号:

回复 “并发编程” 领取《深入理解高并发编程(第1版)》PDF文档。

回复 “并发源码” 领取《并发编程核心知识(源码分析篇 第1版)》PDF文档。

回复 “我要进大厂” 领取《我要进大厂系列之面试圣经(第1版)》PDF文档。

回复 ”限流“ 领取《亿级流量下的分布式解决方案》PDF文档。

回复 “设计模式” 领取《深入浅出Java23种设计模式》PDF文档。

回复 “Java8新特性” 领取 《Java8新特性教程》PDF文档。

回复 “分布式存储” 领取《跟冰河学习分布式存储技术》 PDF文档。

回复 “Nginx” 领取《跟冰河学习Nginx技术》PDF文档。

回复 “互联网工程” 领取《跟冰河学习互联网工程技术》PDF文档。

写在最后

如果你觉得冰河写的还不错,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术,「 冰河技术 」微信公众号更新了大量技术专题,每一篇技术文章干货满满!不少读者已经通过阅读「 冰河技术 」微信公众号文章,成功跳槽到大厂;也有不少读者实现了技术上的飞跃,成为公司的技术骨干!如果你也想像他们一样提升自己的能力,实现技术能力的飞跃,进大厂,升职加薪,那就关注「 冰河技术 」微信公众号吧,每天更新超硬核技术干货,让你对如何提升技术能力不再迷茫!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存