查询
一条sql语句 比如select * from tableA where ID = 10(假设没有索引),执行的时候 首先判断是否有权限,有的话就开始对表操作:
1、调用执行引擎接口“获取表第一行”,判断该行是否ID = 10.如果是 加入结果集
2、调用执行引擎接口“获取表下一行”,判断改行是否ID= 10,如果是 加入结果集
3、如果执行最后时,将结果集返回。
更新
redolog
更新时把记录从磁盘中找到,然后修改后刷入磁盘。整个过程非常耗时,所以InnoDB 设计了 redolog 操作磁盘之前首先写日志 redolog.之后根据redolog 统一操作磁盘,加快了速度。redolog 是有大小限制的,逻辑上是一个环形,当之前的日志被操作到磁盘中后,就可以被重复利用了。
当redolog中 write pos 追上 check point 后 就代表 redolog 满了没有位置可以写 redolog了,从而需要将check point 顺时针操作到磁盘中。这样check point 移动后 就可以又有位置了。
有了redolog InnoDB 就有了crash safe 的 能力。
binlog
binlog 是 MySQL server层的日志,意味着任何存储引擎都可以使用,而redolog是 InnoDB特有的操作日志。主要如如下不同
1、内容不同 binlog 是逻辑上的操作比如 给 某条记录的某列 增加1 而redolog 是物理上的操作,比如某个数据页上做了什么修改。
2、redolog是 循环可用,而binlog是追加写。
3、binlog可以被多个存储引擎使用而redolog 是InnoDB存储引擎特有的。
比如 对于 sql :update T set c = c + 1 where ID = 2
两阶段提交问题
MySQL执行器 使用了两阶段提交来保证redolog和binlog 的数据一致性。
假设 没有两阶段提交,即redolog 和binlog是各自独立的,
1、那么假设c = c+1 ,先写redolog 再写binlog 。再redolog 写完后发生故障,此时故障恢复后会使得内存中的数据c 变为redolog中记录的 从 0 变为 1,而binlog中少了这次数据更新。此时数据就出现了不一致。
2、那么 假设 c = c + 1,先写binlog 再写redolog,所以加入binlog 已经记录了这次数据修改,但是redolog还未被写入,所以此时数据同样会不一致。
两阶段提交同样是解决该问题的。第一阶段是写redolog 进入prepare 状态。第二阶段是写binlog 进入 commit 状态。 经过两阶段之后便可以进行提交事务了。
在使用了两阶段提交后,发生如下问题:
1、假设写redolog之后,发生了故障。此时redolog还未有commit,所以会回滚。
2、假设是在binlog写完之后,发生了故障 此时
如果redolog 有 commit 标识 则恢复的时候直接提交事务。
如果redolog 没有 commit 标识,则检查对应事务的 binlog是否 完整,如果完整 则提交 不完整 则 回滚。
binlog 和 redolog 是通过 事务ID关联起来的。崩溃恢复的时候会顺序扫描redolog
如果发现既有 prepare 又有 commit状态的事务 直接提交。如果只有 prepare 没有 commit状态的事务 需要检查对应事务id binlog 的 完整性。
疑问1 如果只有binlog 没有redolog 是否可以具有crash safe 的能力?
答案:不能。binlog只是记录了逻辑上的操作,如果在上图位置发生故障时,事务2 可以通过引擎补回,但是事务1 虽然被提交了但是并没有记录其是否被刷到磁盘上,丢失的话是不知道怎么补回来的。
疑问2 如果只有redolog 能够具有 crash safe 能力吗?
答案是可以 但是 binlog有着redolog无法替代的能力。一是可以归档。二是可能公司已有的异构系统依赖于binlog ,依靠消费binlog来更新自己的数据,binlog已经有了自己的生态。
疑问3 脏页刷盘的时候时根据 redolog刷盘 还是将内存中的数据刷到磁盘上?
我们要明白redolog只是记录了数据页上的改动 而不是记录了整个数据页的内容。所以数据脏页的刷盘与redolog是没有关系的,只是在恢复数据页的时候起作用。所以正常运行的实例,数据是从buffer pool中 更新到磁盘的,而不是redolog。