MySQL事务日志 (redo log)
事务的隔离性由 锁机制 实现。
而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。
-
REDO LOG 称为 重做日志 ,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性。
-
UNDO LOG 称为 回滚日志 ,回滚行记录到某个特定版本,用来保证事务的原子性、一致性。
1 redo 日志
1 为什么要有redo 日志
缓冲池可以帮助我们消除CPU和磁盘之间的鸿沟,checkpoint机制可以保证数据的最终落盘,然 而由于checkpoint 并不是每次变更的时候就触发 的,而是master线程隔一段时间去处理的。所以最坏的情 况就是事务提交后,刚写完缓冲池,数据库宕机了,那么这段数据就是丢失的,无法恢复。
-
修改与刷盘工作量不匹配
InnoDB是以页为单位进行数据操作的,一页为16K,若果我们只修改了一条数据,刷盘时要将这个页全写入磁盘。
-
随机IO慢
有的记录分布在很多页上,页面随机分布,从内存写到磁盘上时,要将多个页写入磁盘。IO次数很多,浪费时间。
解决
采用WLA( write-ahead logging)技术实现 ,先写日志,再写磁盘,只有当日志写成功时,事务才算提交成功。
2 redo的组成
Redo log可以简单分为以下两个部分
重做日志的缓冲 (redo log buffer) ,保存在内存中,是易失的。
默认大小为16M,最小为1M,最大4096M.
重做日志文件 (redo log file) ,保存在硬盘中,是持久的。
3 redo的整体流程
4 redo log的刷盘策略
MySQL后台有一个maser线程,每过1秒执行一次将redo log buffer 中的数据写入到page cache中,然后写入磁盘。如果mysql挂了,会丢失1秒内数据。当redo log buffer 大小为 innodb_log_buffer_size(16M)的一半时,也会刷盘。
事务提交时,先将日志记录到redo log buffer 中,何时进行写入到磁盘上呢?由InnoDB给出 innodb_flush_log_at_trx_commit 参数决定。它支持三种策略:
设置为0 :表示每次事务提交时不进行刷盘操作。(系统默认master thread每隔1s进行一次重做日 志的同步) 写入到redo log buffer就算事务提交成功。
设置为1 :表示每次事务提交时都将进行同步,刷盘操作( 默认值 ),记录到磁盘上才算成功。
设置为2 :表示每次事务提交时都只把 redo log buffer 内容写入 page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。写入到page cache上就算事务提交成功。
事务提交成功,日志一定在磁盘里,不用担心数据丢失问题。但效率最差。
思考:一个长事务要执行5秒,master线程一秒刷一次盘,此时第五秒mysql挂了,但前4秒数据已经写入到日志磁盘上了,如何解决?
写入page Cache 就算提交成功,如果操作系统挂了,将会丢失1秒内数据
MySQL挂了,丢失1秒内数据