redo log、binlog的提问

redo log、binlog的提问



一、redo log的概念是什么? 为什么会存在

redo log是重做日志。主要用于MySQL异常重启后的一种数据恢复手段,确保了数据的一致性。归根到底是MySQL为了实现WAL机制的一种手段。因为MySQL进行更新操作,为了能够快速响应,所以采用了异步写回磁盘的技术,写入内存后就返回。但是会存在crash后内存数据丢失的隐患,而redo log具备crash safe能力。

二、什么是WAL(write-ahead log)机制, 好处是什么.

WAL机制是写前日志,也就是MySQL更新操作后在真正把数据写入到磁盘前先记录日志。好处是不用每一次操作都实时把数据写盘,就算crash后也可以通过redo log重放恢复,所以能够实现快速响应SQL语句。

三、redo log 为什么可以保证crash safe机制.

因为redo log是每次更新操作完成后,就一定会写入的,如果写入失败,这说明此次操作失败,事务也不可能提交。redo log内部结构是基于页的,记录了这个页的字段值变化,只要crash后读取redo log进行重放就可以恢复数据。(因为redo log是循环写的,如果满了InnoDB就会执行真正写盘)

四、binlog的概念是什么, 起到什么作用, 可以做crash safe吗?

bin log是归档日志,属于MySQL Server层的日志。可以起到全量备份的作用。当需要恢复数据时,可以取出某个时间范围内的bin log进行重放恢复。但是bin log不可以做crash safe,因为crash之前,bin log可能没有写入完全MySQL就挂了。所以需要配合redo log才可以进行crash safe。

五、binlog和redolog的不同点有哪些?

bin log是Server层,追加写,不会覆盖,记录了逻辑变化,是逻辑日志。
redo log是存储引擎层,是InnoDB特有的。循环写,满了就覆盖从头写,记录的是基于页的物理变化,是物理日志,具备crash safe操作。

redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;
binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。

逻辑日志可以给别的数据库,别的引擎使用,已经大家都讲得通这个“逻辑”; 物理日志就只有“我”自己能用,别人没有共享我的“物理格式”

六、物理一致性和逻辑一致性各应该怎么理解?

前者是数据的一致性,后者是行为一致性。

七、执行器和innoDB在执行update语句时候的流程是什么样的?

执行器在优化器选择了索引后,调用InnoDB读接口,读取要更新的行到内存中,执行SQL操作后,更新到内存,然后写redo log,写bin log,此时即为完成。后续InnoDB会在合适的时候把此次操作的结果写回到磁盘。

八、如果数据库误操作, 如何执行数据恢复?

数据库在某一天误操作,就可以找到距离误操作最近的时间节点前的bin log,重放到临时数据库里,然后选择当天误删的数据恢复到线上数据库。

九、什么是两阶段提交, 为什么需要两阶段提交, 两阶段提交怎么保证数据库中两份日志间的逻辑一致性(什么叫逻辑一致性)?

两阶段提交就是对于三步操作而言:

  1. prepare阶段
  2. 写入bin log
  3. commit

redo log在写入后,进入prepare状态,然后bin log写入后,进入commit状态,事务可以提交。

如果不用两阶段提交的话,可能会出现bin log写入之前,机器crash导致重启后redo log继续重放crash之前的操作,而当bin log后续需要作为备份恢复时,会出现数据不一致的情况。所以需要对redo log进行回滚。

如果是bin log commit之前crash,那么重启后,发现redo log是prepare状态且bin log完整(bin log写入成功后,redo log会有bin log的标记),就会自动commit,让存储引擎提交事务。

十、如果不是两阶段提交, 先写redo log和先写bin log两种情况各会遇到什么问题?

假设:

update T set money = 0 + 500 where username = 'test';

1. 先写 redo log 后写 binlog

假设在 redo log 写完,binlog 还没有写完的时候,MySQL 进程异常重启。由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 money 的值是 money + 500。

但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。

然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 money 的值就是 0,与原库的值不同。

2. 先写 binlog 后写 redo log

如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,用户余额 money 的值应当是 0。但是 binlog 里面已经记录了“把 money 从 0 改成 500 这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 money 的值就是 500,与原库的值不同。

可以看到,如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。

简单说,redo log 和 binlog 都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。

3. 总结

先写redo log,crash后bin log备份恢复时少了一次更新,与当前数据不一致。

先写bin log,crash后,由于redo log没写入,事务无效,所以后续bin log备份恢复时,数据不一致。
复制代码


猜你喜欢

转载自blog.csdn.net/weixin_47410172/article/details/127787071