[MySQL] update语句的redo log过程

update语句是如何执行 , 如何将执行后的新数据持久化在磁盘中
可以假设两种情境:

1. 假设MySQL在更新之后只更新内存中的数据就返回,然后再某一时刻进行IO将数据页持久化。这样所有操作都是在内存中,可以想象此时的MySQL性能是特别高的。但是,如果在更新完内存又还没有进行持久化的这段时间,MySQL宕机了,那么我们的数据就丢失了。

2. 另外一种情况:每次MySQL将内存中的页更新好后,立刻进行IO,只有数据落盘后才返回。此时我们可以保证数据一定是正确的。但是,每一次的操作,都要进行IO,此时MySQL的效率变得非常低。

 

我们来看看MySQL是如何做到保证性能的情况下,还保证数据不丢的。

update 表 set a = 1 where id = 1;

如何保证数据一致性

 [MySQL] update语句的redo log过程

 

 

重做日志(redo log)

这里要介绍一个很重要的日志模块,称为rodo log(重做日志)。重做日志是InnoDB引擎特有的。

重做日志在更新数据的时候,会记录在哪个数据页更新了什么数据,并且只要成功的在重做日志记录了这次更新,不需要将内存中的数据页写回磁盘,就可以认为这次更新已经完成了。

1. MySQL里有一个名词,叫WAL技术,WAL的全称是Write-Ahead-Logging,它的关键点就是先写日志,再写磁盘,也就是说只要保证了日志的落盘,数据就一定正确。此时只要保存了日志,就算此时MySQL宕机了,没有将数据页写回磁盘,也可以在之后利用日志进行恢复。

但是,InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB。固定大小也就造成了一个问题,redo log是会被写满的。

 

2. InnoDB采取了循环写的方式。注意看,这里有两个指针。write_pos表示当前写的位置,只要有记录更新了,write_pos就会往后移动。而check_point表示检查点,只要InnoDB将check_point指向的修改记录更新到了磁盘中,check_point将会往后移动。

如果我们把这一行数据所在的内存页更新好了,并且写入了rodo log中,此时将返回修改成功的提示。然后在rodo log中表现为记录了在某一个内存页的更新记录

此时在磁盘中,数据a未改变,在内存中,a改为了1,在rodo log中记录了这个内存页的更新记录,write_pos往后移动。

3. 只有成功的写回了磁盘,check_point才可以往后移动。这个设计,使得rodo log是可以无限重复使用的。

 

[MySQL] update语句的redo log过程

上一篇:odoo 打印执行的sql语句


下一篇:nodejs + mongodb实现模糊查询与全文搜索