MySql 保证事务的原子性和持久性
为了实现事务的原子性和持久性,mysql引入了undo和redo日志(即undo log和redo log)。本篇博客来讲解下undo和redo的概念,以及mysql如何利用undo和redo进行异常宕机恢复。
2、undo日志2.1 作用undo日志记录的是修改前的值
2.2 举例
事务A要将字段age的值由原来的1修改为2,要将name的值由原来的Alice修改为Bob,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日志来保证事务的持久性。
3、redo日志3.1 作用redo日志记录的是修改后最新的数据和冗余的undo日志
3.2 举例事务B要将字段age的值由原来的1修改为2,要将name的值由原来的Alice修改为Bob,redo日志记录的过程表如下:
其中,redo日志必须先于数据写入磁盘(即步骤8和步骤9的顺序不能改变)。因为如果不这样,在数据提交之后再写redo日志,一旦redo日志的写入过程出现异常,将无法保证持久性。
记录redo日志时,先记入redo log buffer,最后再一起写入磁盘,这样可以减少IO,提升性能。
另外,未提交的事务和回滚了的事务也会计入redo日志。
现在假设:如果上面事务B回滚(当做新的事务C),则redo记录的过程表如下:
mysql的恢复策略是:
恢复时,先根据redo重做所有事务(包括未提交和回滚了的)再根据undo回滚未提交的事务。如上,如果事务B异常未提交事务就宕机,恢复时,先根据redo日志将数据恢复为age=2&name=Bob
,然后再根据undo记录的age=1&name=Alice
将数据恢复如初。
如果事务C异常未提交事务就宕机,恢复时,根据redo日志,可以直接恢复至age=1&name=Alice
的初始状态。
redo日志会随着时间推移而越来越大,为了提升redo的恢复性能,引入了checkpoint机制,在恢复的时候,只需要从checkpoint的位置往后恢复即可。
版权声明
本文仅代表作者观点,不代表博信信息网立场。