Mysql三大日志详解

274 阅读4分钟

前言

日志是MySQL的重要组成部分,其中对于开发而言不得不关注三种重要的日志,分别是二进制日志(bin log)、事务日志(redo log、undo log)。

Redo Log(重做日志)

Redo log,也称作重做日志,是一种用来记录数据库中所有更改操作的日志用来保证服务崩溃后,仍能把事务中变更的数据持久化到磁盘上。

什么时候写入Redo Log

image.png

  • 第1步: 先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝

  • 第2步: 生成一条重做日志并写入Redo Log Buffer,记录的是数据被修改后的值

  • 第3步: 当事务commit时,将Redo Log Buffer中的内容刷新到 Redo Log File,对 Redo Log File采用追加写的方式

  • 第4步: 定期将内存中修改的数据刷新到磁盘中

Redo Log 刷盘规则

注意,redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中去,只是刷入到文件系统缓存(page cache)中去,真正的写入会交给系统自己来决定(比如page cache足够大了)。
InnoDB给出innodb_flush_log_at_trx_commit参数,该参数控制commit提交事务时,如何将redo log buffer中的日志刷新到redo log file中。它支持三种策略:

参数说明
0表示每次事务提交时不进行刷盘操作(系统默认master thread 每隔1s进行一次重做日志的同步)
1表示每次事务提交时都将进行同步,刷盘操作(默认值))
2表示每次事务提交时都只把redo log buffer内容写入page cache,不进行同步。由OS自己决定什么时候同步到磁盘文件

Undo Log(回滚日志)

Undo log,也称作回滚日志,是一种用来记录数据库中所有撤销操作的日志。Undo log 用于在事务回滚或数据库发生故障时恢复数据库到正确的状态。比如:当我们执行一条insert语句时,Undo Log就记录一条相反的delete语句。

image.png

MVCC

MVCC(多版本并发控制)是一种用来支持并发访问的技术,常用于数据库系统。

在 MVCC 模型下,数据库系统维护了多个版本的数据。当一个事务修改数据时,数据库系统会在原来的数据版本的基础上创建一个新的数据版本。这样,就可以保证在一个事务修改数据的同时,其他事务仍然可以访问原来的数据版本。

隐藏字段

对于一个InnoDB存储引擎,一个聚簇索引(主键索引)的记录之中,一定会有两个隐藏字段trx_id和roll_pointer,这两个字段存储于B+树的叶子节点中,分别对应记录着两列信息:

  • trx_id:只要有任意一个事务对某条聚簇索引记录进行修改,该事务id就会被记录到该字段里面。
  • roll_pointer:当任意一个聚簇索引记录被修改,上一个版本的数据记录就会被写入Undo Log日志里面。那么这个roll_pointer就是存储了一个指针,这个指针是一个地址,指向这个聚簇索引的上一个版本的记录位置,通过这个指针就可以获得到每一个历史版本的记录。

Read View

Read View 存放着一个列表,这个列表用来记录当前数据库系统中活跃的读写事务,也就是已经开启了,正在进行数据操作但是还未提交保存的事务。可以通过这个列表来判断某一个版本是否对当前事务可见。其中,有四个重要的字段:

  • creator_trx_id:创建当前Read View所对应的事务ID
  • m_ids:所有当前未提交事务的事务ID,也就是活跃事务的事务id列表
  • min_trx_id:m_ids里最小的事务id值
  • max_trx_id:InnoDB 需要分配给下一个事务的事务ID值

Bin Log(备份日志)

Bin Log记录的是逻辑日志,即原始的SQL语句,是MySQL自带的。
日志格式如下

参数说明
Statement记录原始SQL语句,会导致更新时间与原库不一致
Row记录每行数据的变化,保证了数据与原库一致,缺点是数据量较大
MixedStatement和Row的混合模式,默认采用Statement模式,涉及日期、函数相关的时候采用Row模式,既减少了数据量,又保证了数据一致性。

什么时候写入Bin Log?

Bin Log采用追加写入的模式,并不会覆盖原有日志,所以可以用来恢复到之前某个时刻的数据。

Bin Log也是采用WAL模式,先写日志,再写磁盘。

刷盘机制可以由sync_binlog配置参数指定。

参数说明
0(延迟写)每次提交事务都不会刷盘,而是由系统来决定,存在数据丢失风险
1(实时写)每次提交事务都会刷盘,性能较差。
N(延迟写)提交N个事务后才会刷盘。