redo(记录了事务的行为,可以很好的通过其对页进行“重做”操作)
- 包含易失的redo log buffer和持久的redo log file两部分
- 存于redo log file(重做日志文件中)
- 维护持久性
- 页操作
在一个事务中的每一次SQL操作之后都会写入一个redo log到buffer中,在最后COMMIT的时候,必须先将该事务的所有日志写入到redo log file进行持久化(这里的写入是顺序写的),待事务的COMMIT操作完成才算完成。
redo
参数 innodb_flush_log_at_trx_commit 用来控制重做日志刷新到磁盘的策略,该参数有3个值:0、1和2。
0:表示事务提交时不进行写redo log file的操作,这个操作仅在master thread中完成(master thread每隔1秒进行一次fsync操作)。
1:默认值,表示每次事务提交时进行写redo log file的操作。
2:表示事务提交时将redo log写入文件,不过仅写入文件系统的缓存中,不进行fsync操作。
对比binlog
binlog为了解决Mysql主从备份而产生
* 内部XA:redo log和bin log的数据一直性和完整性的保证
* 外部XA:分布式事务
内部XA(二段式提交),由于需要遵循WAL原则,binlog的过程需要嵌入到事务提交的流程中:
* prepare过程
* commit过程
在MySQL数据库中还有一种二进制日志(binlog),从表面上来看它和redo log很相似,都是记录了对数据库操作的日志,但是,它们有着非常大的不同。
- redo log是在MySQL的InnoDB引擎层产生,而binlog则是在MySQL的上层产生,它不仅针对InnoDB引擎,其他任何引擎对于数据库的更改都会产生binlog。
- 两种日志记录的内容形式不同,binlog是一种逻辑日志,其记录的是对应的SQL语句。而redo log则是记录的物理格式日志,其记录的是对于每个页的修改。
- 两种日志记录写入磁盘的时间点不同,binlog只在事务提交完成后一次性写入,而redo log在上面也说了是在事务进行中不断被写入,这表现为日志并不是随事务提交的顺序进行写入的。
undo
- 分为insert undo log(insert,insert只对本身事务可见,对其他事务无影响)和update undo log(update/delete)
- 存于数据库中的undo segment(段)中
- 用于回滚
- 用于MVCC(实现非锁定读),读取一行记录时,若已被其他事务占据,则通过undo读取之前的版本
- 维护原子性
- 行操作(回滚行记录到某个版本)
undo是逻辑日志,只是将数据库逻辑的恢复到执行语句或事务之前。
InnoDB存储引擎的行结构
InnoDB表数据的组织方式为主键聚簇索引,二级索引中采用的是(索引键值, 主键键值)的组合来唯一确定一条记录。
InnoDB表数据为主键聚簇索引,mysql默认为每个索引行添加了4个隐藏的字段,分别是:
- DB_ROW_ID:InnoDB引擎中一个表只能有一个主键,用于聚簇索引,如果表没有定义主键会选择第一个非Null的唯一索引作为主键,如果还没有,生成一个隐藏的DB_ROW_ID作为主键构造聚簇索引。
- DB_TRX_ID:最近更改该行数据的事务ID。
- DB_ROLL_PTR:undo log的指针,用于记录之前历史数据在undo log中的位置。
-
DELETE BIT:索引删除标志,如果DB删除了一条数据,是优先通知索引将该标志位设置为1,然后通过(purge)清除线程去异步删除真实的数据。
简化过程
不需要实时以同步的方式刷盘,数据可以后台异步写入磁盘(根据 innodb_flush_log_at_trx_commit参数值0,1,2来决定)
redo log写入磁盘是顺序IO
undo log也写入到redo log中
redo 缓存刷盘规则:
- 事务提交时
- 当log buffer 中一半的内存空间已经被使用时
- log checkpoint时
check point
check point机制是为了减少实例恢复的时间(如果在某个时间点,脏页的数据被刷新到了磁盘,系统就把这个刷新的时间点记录到redo log的结尾位置,在进行恢复数据的时候,checkpoint时间点之前的数据就不需要进行恢复了,可以缩短时间)
- 缓冲池不够用时,触发checkpoint,将脏页刷盘
- 重做日志不够用时,刷新磁盘
脏页:一般业务运行过程中,当业务需要对某张的某行数据进行修改的时候,innodb会先将该数据从磁盘读取到缓存中去,然后在缓存中对这条数据进行修改,这样缓存中的数据就和磁盘的数据不一致了,这个时候缓存中的数据就称为dirty page,只有当脏页统一刷新到磁盘中才会是clean page
在COMMIT的时候,InnoDB不会将dirty data page写盘。之所以强调这个是因为,很容易让人想到,提交改变就是将所有东西写到一个持久媒介上。
其实,commit时只有log记录需要写。写dirty data page只可能发生在overflow或checkpoint时刻,因为它们的内容是多余的。
网友评论