mysql保证原子性和持久性的利器:undo和redo

为了实现事务的原子性和持久性,mysql引入了undo和redo日志。本文讲解下undo和redo的概念,以及mysql如何利用undo和redo进行异常宕机恢复。

undo 日志

undo日志记录的是修改前的值。

比如:

事务A要将字段age的值由原来的1修改为2,要将name的值由原来的Alice修改为Bob,undo日志记录的是:

如果在上表第三步之前数据库挂了,则最终数据和日志均为原数据;如果第三步及以后出现异常,则undo已经记录了原来的值,则可以利用undo日志将数据恢复为原数据。

在事务提交之后,undo不会被马上删除,而是放入待删除队列,由purge线程来判断是否删除和处理。

在mysql5.6之前,undo只存在于共享表空间中,之后的版本中,可以配置为独立的文件。

undo内部默认128个回滚段槽(rseg slot),每个rseg slot内部有1024个回滚段(rollback segment)。其中:

▪ slot0——共1个,预留给系统表空间

▪ slot1-slot31——共31个,预留给临时表空间

▪ slot32-slot127——共96个,预留给undo独立表空间

由于undo日志会被清理掉,不能保证事务的持久性,因此引入redo日志来保证事务的持久性。

redo日志

redo日志记录的是修改后最新的数据和冗余的undo日志。

比如:

事务B要将字段age的值由原来的1修改为2,要将name的值由原来的Alice修改为Bob,redo日志记录的是:

其中,redo日志必须先于数据写入磁盘,因为如果不这样,在数据提交之后再写redo日志,一旦redo日志的写入过程出现异常,将无法保证持久性。

记录redo日志时,先记入redo log buffer,最后再一起写入磁盘,这样可以减少IO,提升性能。

未提交的事务和回滚了的事务也会计入redo日志。

如果上面事务B回滚(当做新的事务C),则redo记录的是:

mysql的恢复策略

mysql的恢复策略是:恢复时,先根据redo重做所有事务(包括未提交和回滚了的),再根据undo回滚未提交的事务。

如上,如果事务B异常未提交事务就宕机,恢复时,先根据redo日志将数据恢复为age=2&name=Bob,然后根据undo记录的age=1&name=Alice将数据恢复如初。

如果事务C异常未提交事务就宕机,恢复时,根据redo日志,可以直接恢复至age=1&name=Alice的初始状态。

redo日志会随着时间推移而越来越大,为了提升redo的恢复性能,引入了checkpoint机制,在恢复的时候,只需要从checkpoint的位置往后恢复即可。

—END—

自由,

是因为自己真的有方向。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181108G0N0NX00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券