MySQL两大重要日志模块
author:陈镇坤27
创建时间:xx
编辑时间:2021年11月11日10:21:01;2021年11月12日18:08:56;2021年11月23日10:10:50、2021年11月29日21:33:20;2022年2月17日
文章目录
——————————————————————————————————————————
写在前面:关联的篇章是第8、9、12、15、23篇;
redo log(重做日志)
问:什么是redo log?
答:MySQL的Innodb引擎独有的物理日志系统,循环写,存储数据的物理变化,有事务保持。
问:什么是WAL?
答:WAL是write ahead log的英文缩写。MySQL进行数据更新时,选择将更新操作(物理)记入redo log当中,引擎会在适当的时候(内存中的数据页被替换时等等)将其同步到磁盘。
————(编辑2021年11月12日18:08:56、2022年3月8日)
PS:这块和第九章的change buffer理解会起冲突,我还是用完整的方式解释一下:MySQL进行数据更新时,若数据更新仅涉及到二级索引,且目标数据页不在内存中,则会记录一条数据页变更记录在change buffer中,并记录一条change buffer的变动记录到redo log中,如果目标数据页在内存中,则只会记录一条数据页变更记录到redo log中。
当目标数据页不在内存时,change buffer会在适合的时机(内存中加载有对应的数据页时),将数据同步到内存,内存中的数据最后同步到磁盘(同步磁盘的过程也会进行redo log记录)。本质上,redo log的作用是crash safe,例如在change buffer中的数据还没同步,但数据库断电了,此时通过redo log回复数据。
问:什么是crash-safe?
答:通过redo log当数据库异常重启时,可以保证更新数据不丢失。(第23篇有较详细解释)
问:redo log的特性是什么?
答:循环写,事务
binlog:归档日志
问:什么是binlog?
答:MySQL的server层共有日志,覆盖写,存储数据的更新原始记录(statement或其它)
问:redo log和binlog的主要区别
1、redolog存在于Innodb引擎,binlog存在于server层
2、redolog具备crash-safe特点,binlog不具备;
3、redo log记录的是某个数据页更改的物理记录,binlog记录的是某行数据的更改的逻辑记录(statement格式:执行的sql,row格式:前后两条数据)
4、redo log是循环写,binlog是追加写(不覆盖)
二阶段提交
问:DML时redo log和binlog如何参与执行流程?
答:pg:
update T set id = id + 1 where id = 2;
1、执行器调用引擎,查询id = 2的数据
2、引擎通过搜索树去搜索id = 2的数据,如果该数据在内存中,则直接返回(内存中的数据),否则从磁盘(这条sql只更新了一级索引,所以不会触发change buffer的缓存功能)读入内存再返回
3、执行器对该行数据进行统计上的 + 1 操作((按server层接收计算)表示扫描到一行),然后调用引擎接口进行写操作
4、引擎调用redo log进行记录,同时写入内存中。redo log处于prepare状态,告知执行器完成,可以提交事务。
5、执行器生成本次操作的binlog,再把binlog写入磁盘。
6、执行器调用引擎的提交事务接口,把刚刚的redo log日志改成commit状态。
问:什么是二阶段提交?
答:跨系统保持数据一致性的方案。
问:如果没有二阶段提交,会有什么问题?
答:
如果先binlog再redo log,可能会出现binlog多记录数据的情况(binlog记录成功后,异常重启,redo log和数据事务回滚)
如果先redo log再binlog,则可能出现binlog少记录数据的情况(数据库多了一条binlog没有的数据)
两种情况都导致日志的回溯不能保证数据能够真实还原。
问:binlog和redo log有什么重要参数吗?
答:sync_binlog = 1 :每次事务的binlog都提交到磁盘;innodb_flush_log_at_trx_commit = 1:每次事务的redo log都提交到磁盘