目录

Mysql之三大日志

李羽秋
李羽秋 2023年02月01日  ·  阅读 1,087

Mysql之三大日志

1. 简介

日志是数据库的重要组成部分,记录着数据库运行期间各种状态信息。包括错误日志、查询日志、慢查询日志、事务日志、二进制日志等几大日志。我们接下来重点介绍一下二进制日志(bin log) 和事务日志(包括redo log 和 undo log)。

2. undo 日志文件:记录数据被修改的样子(回滚日志)

在操作任何数据之前,首先将数据备份到一个地方,这个存储数据备份的地方称之为undo log。如果出现了错误或者用户执行了rollback语句,系统可以利用undo log 的备份将数据恢复到事务开始之前的状态。

undo log是逻辑日志(记录的是逆向回滚的逻辑,而不是实际的值),可以理解为:

  • 当delete一条记录的时候,undo log中会记录一条对应的insert记录
  • 当insert一条记录的时候,undo log 会记录一条对应的delete记录
  • 当update一条记录的时候,undo log中会记录一条对应的update记录

image-20220511192830285

3. redo 日志文件:记录数据被修改后的样子

innodb为了提高磁盘I/O的读写性能,存在一个buffer pool的内存空间,数据读入会缓存到buffer pool,事务的提交则实时更新到buffer pool,而不实时同步到磁盘(innodb 是按 16KB 一页同步的,一事务可涉及多个数据页,实时同步会造成浪费,随机I/O)。事务暂存在内存,则存在一致性问题,为了解决系统崩溃,保证事务的持久性,我们只需要把事务对应的redo日志持久到磁盘即可。

3.1 redo log 日志好处

  • redo 日志所用的空间非常小

    存储表空间ID、页号、偏移量以及需要更新的值所需的存储空间很小

  • redo 日志是顺序写入磁盘的

    在执行事务过程中,每执行一条语句,就可能产生若干个redo日志,这些日志按照产生的顺序读入磁盘,也就是使用顺序IO,速度比随机更快

3.2 redo 日志刷盘时机

  • 当log buffer 的总容量达到50%,则刷新日志到磁盘
  • 事务提交时,也需要将同步到磁盘
  • 后台线程,每一秒同步一次
  • 关闭mysql 服务
  • 做checkpoit 的时候
    • redo 的空间有限的。若redo日志对应的数据页如果被同步到磁盘,则redo日志也可被回收利用了。

4. bin log

上面介绍到的redo log是 InnoDB 存储引擎特有的日志文件,而bin log属于是 MySQL 级别的日志。 redo log记录的东西是偏向于物理性质的,如:“对什么数据,做了什么修改”。bin log是偏向于逻辑性质的,类似于:“对 students 表中的 id 为 1 的记录租了更新操作” 两者的主要特点总结如下:

性质 redo Log bin Log
文件大小 redo log 的大小是固定的(配置中也可以设置,一般默认的就足够了) bin log 可通过配置参数max_bin log_size设置每个bin log文件的大小(但是一般不建议修改)。
实现方式 redo logInnoDB引擎层实现的(也就是说是 Innodb 存储引起过独有的) bin log是 MySQL 层实现的,所有引擎都可以使用 bin log日志
记录方式 redo log 采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。 bin log 通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上
使用场景 redo log适用于崩溃恢复(crash-safe)(这一点其实非常类似与 Redis 的持久化特征) bin log适用于主从复制和数据恢复

4.1 bin log 格式

bin log 由三种格式:

  • Statement: 每一条会修改数据的SQL都会记录在binlog中
  • Row: 不记录SQL语句上下文信息,仅保存哪个记录被修改
  • Mixed: Statement 和 row 混合体

4.1.1 Statement

Statement模式只记录执行的SQL,不需要记录每一行数据,因此极大的减少binlog日志量,避免了大量的IO操作,提升了系统的性能。

但是正是由于Statement模式只记录SQL,而如果一些SQL中包含了函数,那么可能会出现执行结果不一致的情况。比如说uuid()函数,每次执行的时候都会生成一个随机字符串,在master中记录了uuid,当同步到slave之后,再次执行,就获取到另外一个结果。所以使用Statement 格式会出现一些数据一致性问题。

4.1.2 Row

从Mysql5.1.5版本开始,binlog引入了Row格式,Row格式不记录SQL语句上下文相关信息,仅仅只需要记录某一条记录被修改成什么样子。

Row格式的日志内容会非常清楚地记录下每一行数据修改的细节,这样就不会出现Statement中存在的那种数据无法被正常复制的情况。

不过row格式也有一个很大的问题,那就是日志量太大了,特别是批量update、整表delete、alter表等操作,由于要记录每一行数据的变化,此时会产生大量的日志,大量的日志也会带来IO性能问题

4.1.3 Mixed

从 MySQL5.1.8 版开始,MySQL 又推出了 Mixed 格式,这种格式实际上就是 Statement 与 Row 的结合。

在 Mixed 模式下,系统会自动判断该用 Statement 还是 Row:一般的语句修改使用 Statement 格式保存 binlog;对于一些 Statement 无法准确完成主从复制的操作,则采用 Row 格式保存 binlog。

Mixed 模式中,MySQL 会根据执行的每一条具体的 SQL 语句来区别对待记录的日志格式,也就是在 Statement 和 Row 之间选择一种。

4.2 使用场景

  • MySQL 主从复制时:在主机上开启 binlog,主机将 binlog 同步给从机,从机通过 binlog 来同步数据,进而实现主机和从机的数据同步。
  • MySQL 数据恢复,通过使用 mysqlbinlog 工具再结合 binlog 文件,可以将数据恢复到过去的某一时刻。

5. redo log 和binlog 区别

  • redo log 是InnoDB引擎特有的;binlog是MYSQL的Server层实现的,所有引擎都可以使用,redo log是物理日志,记录的是“在缪个数据页上做了什么修改"
  • binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如”ID=2这一行c字段加1"
  • redo log 是循环写的,空间固定会用完;binlog是可以追加写入的。追加写是binlog文件写道一定大小会切换到下一个,不会覆盖以前的日志。

6. redo log记录事务是两阶段提交

如果redo 不是两阶段提交,当先写redo,然后写binlog时出现了故障,会导致binlog主从复制时主从库数据不一致。当先写bin log时,、

在写 redo log出现了故障,会导致从库多出未提交的脏数据,主从库会不一致。

image-20220512133127507

参考:https://juejin.cn/post/7075573501922410533

分类: mysql
标签: