Mysql之三大日志
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记录
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 log 是InnoDB 引擎层实现的(也就是说是 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出现了故障,会导致从库多出未提交的脏数据,主从库会不一致。