简介

除了前两篇的日志学习,MySQL还有两个特殊的日志----回滚日志(undo log)和重做日志(redo log),统称事务日志。
事务日志,顾名思义是为了保障数据的原子性和一致性。

详解

MySQL数据存储

MySQL中数据是以页为单位,查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到 Buffer Pool 中。后续的查询都是先从 Buffer Pool(缓冲池)中找,没有命中再去硬盘加载,减少硬盘 IO 开销,提升性能。
更新表数据的时候,也是如此,发现 Buffer Pool(缓冲池)里存在要更新的数据,就直接在 Buffer Pool 里更新。

回滚日志

回滚日志在异常发生时,对已经执行的操作进行回滚。
所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,可以利用回滚日志中的信息将数据回滚到修改之前。并且,回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。

重做日志

重做日志是InnoDB存储引擎独有的,在MySQL实例挂了或宕机了,重启时,InnoDB存储引擎会使用重做日志恢复数据,保证数据的持久性与完整性。
重做日志有个自己的缓冲池----redo log buffer(重做日志缓冲池)。在InnoDB存储引擎更新数据到Buffer Pool时,会同步记录到redo log buffer中。之后再将更新记录刷盘(将缓冲数据更新到磁盘中)到重做日志的文件中。
InnoDB存储引擎支持三种刷盘策略,可以通过设置innodb_flush_log_at_trx_commit参数改变刷盘策略:

0表示每次事务提交时不进行刷盘操作
1表示每次事务提交时都将进行刷盘操作(默认值)
2表示每次事务提交时都只把 redo log buffer 内容写入 page cache(文件系统缓存)

另外,InnoDB 存储引擎有一个后台线程,每隔1秒,就会把 redo log buffer 中的内容写到文件系统缓存(page cache),然后调用fsync刷盘。也就是说,一个没有提交事务的 redo log 记录,也可能会刷盘。

结语

回滚日志是记录旧值,重做日志是记录新值。例如要将某条数据由 0 更新成 1 ,回滚日志会记录旧值 0 ,重做日志会记录新值 1 。