这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记
redo log 事务日志、重做日志
恢复到丢失的修改
InnoDB独有,为MySQL提供了崩溃恢复能力
- MySQL中数据以页为单位
- 查询或者修改数据时,会从硬盘加载一个数据页到
Buffer Pool - 查询或修改会在
Buffer Pool中进行,如果没有命中数据再去硬盘加载,以减小IO开销 - 然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(
redo log buffer),接着刷盘到redo log文件
redo log buffer 刷盘时机
innodb_flush_log_at_trx_commit:
- 0:每次事务提交时不刷盘
- 1:每次事务提交时刷盘,默认
- 2:每次事务提交时写到文件系统page cache
进入了redo log buffer,会受到MySQL和物理机影响
进入了page cache,只会受到物理机宕机影响
事务提交即刷盘,不会有数据损失
redo log 日志文件组
多个文件组成循环队列,write pos``记录下一个可写的位置,checkpoint`记录上次擦除后的位置
每次MySQL加载redo log恢复数据时,会擦除加载过的记录;当队列首尾相遇时,会擦除一些记录。
binlog 二进制日志、归档日志
redo log是物理日志,记录“在某个数据页上做了什么修改”。属于存储引擎。
binlog是逻辑日志,记录语句的原始逻辑,如给xxx加1。属于MySQL server层,所以不管用什么引擎,发生了表数据更新,都会产生日志。数据库集群通过binlog 同步数据
binlog会顺序记录所有使数据更新的逻辑操作。
记录格式
statement:记录SQL语句原文row:记录原文及具体数据, 需要通过工具导出查看mixed:折中手段,系统判断记录语句会导致不一致,就选择row格式
写入机制
事务执行中 → binlog cache → 事务提交 → binlog
sync_binlog:
- 0:提交事务只wirte,系统决定fsync时机,默认
- 1:提交事务会fsync刷盘
- N:通常只write,累计提交N个事务后fsync刷盘
同上,主机宕机会丢失page cache,MySQL挂了会丢失binlog cache
两阶段提交
redo log作用:崩溃恢复的保障;写入时机:伴随着事务过程写入。
binlog作用:数据库集群同步数据;写入时机:事务提交写入。
引出问题:redo log在事务未完成时写入了数据更新,但提交出了错,更新没有写入binlog,那么主数据库从redolog恢复数据得到了更新,而从数据库从binlog同步数据而没有得到更新。数据不一致。
解决问题:redo log侧将写入拆成prepare和commit,InnoDB两阶段提交。
prepare阶段的日志,如果binlog中找不到对应事务id不会用来恢复。
undo log 回滚日志
回滚到修改之前
提供事务的原子性
事务进行的修改会先记录到undolog中,且这个记录先于具体数据的持久化
回滚时能通过记录的数据旧值回滚