Mysql crash-safe详解

1,063 阅读2分钟

redo log

redo log是物理日志,记录的是“在某个数据页上做了什么修改”,它是循环写的,文件大小固定,是InnoDB引擎特有的。

bin log

bin log是逻辑日志,记录的是逻辑SQL语句。

格式

bin log有两种格式,分别是STATEMENT和ROW。

  • STATEMENT:日志记录的是逻辑SQL语句
  • ROW:日志记录的是表的行更改情况

redo log 和bin log的配置使用实现了crash-safe

crash-safe:即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。这里提交的概念是指,日志能够成功写入redo log,否则告之客户端提交失败

流程

假设数据库执行语句

update t set n = n+1 where id =1
  1. 数据库执行器从内存中查找表n id为1的值,如果能找到,直接返回该值n,否则,要从磁盘中查询、读取该值;
  2. 执行器拿到引擎层给的数据,对将n设置为n+1,再调用引擎层写入新数据;
  3. 引擎层拿到这一行数据,先将该数据写入redo log,并将状态设定为prepared,且告知执行器执行完成了,事务随时可以提交;
  4. 执行器生成这个操作的 bin log,并将bin log写入磁盘;
  5. 执行器调用引擎层事务提交的接口,将刚刚写入的redo log的状态设定为commited,更新完成。

crash 分析

  1. 如果数据在上述流程第3步之后crash,通过redo log恢复时检测到事务尚未提交,事务本身会回滚,两阶段数据一致;
  2. 如果数据在上述流程第4步之后crash,恢复时检测到bin log中存在该操作,且redo log处于prepared状态,重启时会自动commit。

其他流程

  1. 先写redo log,再写bin log,如果写完redo log发生crash,这样重启恢复的时候,redo log已经commit。造成bin log和 redo log不一致。如果主从复制使用该bin log,就会发生主机和从机数据不一致的情况;
  2. 先写bin log,再写redo log,如果写完bin log发生crash,自动重启后,由于没有通过commit来提交,事务会发生回滚。而bin log是存在该记录的,如果主从复制使用该bin log,就会发生主机和从机数据不一致的情况;