数据库06——事务的实现原理2

146 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

持久性——redolog

redo log重做日志,实现事务的持久性

由于磁盘IO非常缓慢,内存非常快,所以先将数据写入缓冲池中,再以一定的频率刷入磁盘(checkPoint机制)来平衡IO速度,(使用索引缓解磁盘IO缓慢的问题),但缓冲池中的数据可能来不及刷入磁盘就丢失,不符合事务持久性,所以将数据先写入redo log日志,再入写磁盘,只有redo log日志写入成功,才算事务提交成功。若数据未写入磁盘就宕机,可以通过redolog日志来恢复。

redolog日志的写入是在文件尾部追加数据(顺序IO),写入速度比将数据写入磁盘更快(随机IO)。

redo log也有缓冲区的,叫做redo log buffer(重做日志缓冲),InnoDB引擎会在写redo log的时候先写redo log buffer,然后也是以一定的频率刷入到真正的redo log中,这里的同步策略有三种:

  • master线程每秒将buffer刷到到redo log中
  • 每个事务提交的时候会将buffer刷到redo log中
  • 当buffer剩余空间小于1/2时,会被刷到redo log中

事务更新数据的操作流程:

img

为什么分两段式提交(redolo prepare、redolog commit)——防止主从不同步(数据库内部分布式事务

为了保证redo logbin log的数据同步,如果redo log直接提交,bin log还没来得及记录数据就宕机了,这时从机就没办法和主机保持数据同步,所以让binlog(存sql) 写入成功后就将prepare改为commit。(两段式提交就是指redo log有prepare和commit两种状态)

实际情况下:

通过两段式提交我们知道redolog和binlog在各个阶段会被打上prepare或者commit的标识,同时还会记录事务的XID,有了这些数据,在数据库重启的时候,会先去redo log里检查所有的事务,如果redo log的事务处于commit状态,那么说明在commit后发生了crash,此时直接把redo log的数据恢复就行了,如果redo log是prepare状态,那么说明commit之前发生了crash,此时binlog的状态决定了当前事务的状态,如果binlog中有对应的XID,说明binlog已经写入成功,只是没来的及提交,此时再次执行commit就行了,如果binlog中找不到对应的XID,说明binlog没写入成功就crash了,那么此时应该执行回滚。

为什么不只用redo log?

因为redo log满了就会覆盖之前的数据继续写。

那为什么不可以通过binlog来恢复未落盘的数据

这是因为binlog不知道哪些数据落盘了,所以不知道哪些数据需要恢复。对于redo log而言,在数据落盘后对应的redo log中的数据会被删除,那么在数据库重启后,只要把redo log中剩下的数据都恢复就行了。

  • 真实数据会先存到缓冲池中,再由后台线程将数据同步到磁盘
  • redolog可以在数据同步失败的时候恢复数据

img

redo log通常是物理日志,记录的是页的物理修改操作;存储二进制数据,便于恢复

undo log是逻辑日志,根据每行记录进行记录。保存sql,便于读取