前言
日志是MySQL的重要组成部分,其中对于开发而言不得不关注三种重要的日志,分别是二进制日志(bin log)、事务日志(redo log、undo log)。
Redo Log(重做日志)
Redo log,也称作重做日志,是一种用来记录数据库中所有更改操作的日志用来保证服务崩溃后,仍能把事务中变更的数据持久化到磁盘上。
什么时候写入Redo Log
-
第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语句。
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 | 记录每行数据的变化,保证了数据与原库一致,缺点是数据量较大 |
| Mixed | Statement和Row的混合模式,默认采用Statement模式,涉及日期、函数相关的时候采用Row模式,既减少了数据量,又保证了数据一致性。 |
什么时候写入Bin Log?
Bin Log采用追加写入的模式,并不会覆盖原有日志,所以可以用来恢复到之前某个时刻的数据。
Bin Log也是采用WAL模式,先写日志,再写磁盘。
刷盘机制可以由sync_binlog配置参数指定。
| 参数 | 说明 |
|---|---|
| 0(延迟写) | 每次提交事务都不会刷盘,而是由系统来决定,存在数据丢失风险 |
| 1(实时写) | 每次提交事务都会刷盘,性能较差。 |
| N(延迟写) | 提交N个事务后才会刷盘。 |