binlog和redoLog在崩溃恢复上的作用

what:

  崩溃恢复:即使在数据库宕机的情况下,也会出现操作一半的情况;

  bin log :是server层的归档日志,不足以实现崩溃恢复(crash-safe);

  redo log :是物理日志,具有崩溃恢复的能力;

 

diff:

  1、适用对象:

    bin log: 是 MySQL 的 Server 层实现的,所有引擎都可以使用;

    redo log :是 InnoDB 引擎特有的;

  2、写入内容:

    bin log:是逻辑日志。记录的是这个语句的原始逻辑,比如 “给 id = 1 这一行的 age 字段加 1”;

    redo log :是物理日志。记录的是 “在某个数据页上做了什么修改”;

  3、写入方式:

    bin log:是追加写入。“追加写” 是指 bin log 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。那么就会出现“没有标志能让 InnoDB 从 bin log 中判断哪些数据已经刷入磁盘了,哪些数据还没有”;

    redo log :是循环写入。即空间固定会被用完;那么“会记录未刷入磁盘的日志,已经刷入磁盘的数据就会删掉”;

 

how:

  核心方案:redo log采用两阶段提交。即redo log的写入拆分为了2个步骤:preparecommit

 

   SQL 查询语句的执行过程:(具体流程入下图)

    1、MySQL 客户端与服务器间建立连接,客户端发送一条查询给服务器

    2、服务器检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果;否则进入下一阶段;

    3、服务器端进行 SQL 解析、预处理,生成合法的解析树;

    4、由优化器生成对应的执行计划

    5、执行器根据执行计划(优化器生成),调用相应的存储引擎的 API 来执行,并将执行结果返回给客户端;

      

 

  SQL更新语句的执行过程:相对查询多了,两日志模块 bin log 和 redo log的操作。

    以“update tablese tage=age+1 where id=1;”为栗子:

    注意:以下操作和查询的前4步相同。

    1、执行器:找存储引擎取到 id = 1 这一行记录;

    2、存储引擎:根据主键索引到这一行,如果 id = 1 这一行所在的数据页本来就在内存池(Buffer Pool)中,就直接返回给执行器;否则,需要先从磁盘读入内存池,然后再返回;

    3、执行器:拿到存储引擎返回的行记录,把 age 字段加上 1,得到一行的记录,然后再调用存储引擎的接口写入这行新记录;

    4、存储引擎:将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务

          注意:此处的“事务”是提交过程中的一个小步骤,也是最后一步,而非 sql 语句中的提交事务 commit 命令

    5、执行器生成这个操作的 bin log,并把 bin log 写入磁盘;

    6、执行器:调用存储引擎的提交事务接口;

    7、存储引擎:把刚刚写入的 redo log 状态改成提交(commit)状态,更新完成

    具体如下图:

    

 

 

 why():

   怎么判断bin log 是不是完整的?

    1、statement 格式的 bin log,最后会有 COMMIT;

    2、row 格式的 bin log,最后会有 XID event;

    3、对于 bin log 可能会在中间出错的情况,MySQL 5.6.2 版本以后引入了 binlog-checksum 参数,用来验证 bin log 内容的正确性;

 

  为何redo log有崩溃恢复能力?

    1、如果 redo log 里面的事务是完整的,也就是已经有了 commit 标识,则直接提交;

    2、如果 redo log 里面的事务处于 prepare 状态,则判断对应的事务 binlog 是否存在并完整

      a、如果 binlog 存在并完整,则提交事务;

      b、否则,回滚事务;

 

  栗子1:“数据库在写入 redo log(prepare) 阶段之后、写入 binlog 之前,发生了崩溃”。

    分析:此时,redo log处于prepare状态,但是binlog没有完成,事务就需要回归。

    原因:binlog 还没有写入,之后从库进行同步的时候,就会缺少数据,但是主库中已经有数据了,结果就是“主从不一致”,所以主库的操作需要回滚。

 

  栗子2:“数据库在写入 binlog 之后,redo log在commit之前发生了崩溃”。图如下:

    分析:redo log处于prepare状态,binlog完整了,事务直接提交。

    原因: binlog 写入成功,从库能够同步过去。此时主库并没有完成这个操作,所以主备就不一致了。那么在主库上需要提交这个事务。

              

 

 

  

 

  

 

posted @ 2022-03-10 22:50  修心而结网  阅读(796)  评论(0编辑  收藏  举报