当前位置:   article > 正文

mysql undo log 查看_了解mysql的undo log

undolog 查看

第一次了解mysql的时候,看到了undo log这个名词,却不知道undo log是干什么,为了能够继续看明白一些mysql的资料,不得不先弄明白undo log是什么? undo log的原理是什么?它与数据库的其它特性如何配何。

这篇笔记只从原理上分析,不涉及具体的实现方法。

undo log是什么?

undo log是一种日志,日志中记录对于数据库的反向操作。

如果把数据库的内容当做一种状态机,那么数据的写操作就是修改状态机的命令,而undo 就对应修改状态机的反向命令。

所以理论上每一个对于状态机修改的命令都会产生对应一条相当的undo log,以便事务回滚的时候,能够把状态机修改到事务原来的样子。

假如我们有一个事务:

create table table1(c1 int);

begin transaction;

insert into table1 (100); //数据库执行这一条命令的时候应该产生一条undo日志,能够把这语句对于状态机的修改回复到原来没有修改的状态 , undo 应该是 delete table1 where c1 = 100;

insert into table1(200); // undo 应该是 delete table1 where c1 = 200;

update table1 set c1 = 300 where c1 = 200; // undo: update table1 set c1 = 200 where c1 = 300

rollback;

为什么要有undo log, 或者说undo log解决了什么问题?

其实这个问题问的不好,因为undo是设计出来,没有什么直接的因素说非得有undo log, 自己比较熟习的postgres就没有undo log。下面就与postgres进行比较,来看mysql为什么有undo

mysql与postgres都是基于mvcc的,但是mysql与postgres对于mvcc的实现不太一样。

为什么要有mvcc? 因为mvcc与它的前辈lock based相比,能够实现读写不冲突这一个特性,如果没有mvcc,一个事务读一条数据,另外一个事务写同一条数据,这两个事务是无法并发执行的,后一个事务必须要等前一个事务执行完成之后才能执行,但是有了mvcc,这两个事务就可以并发执行,这及大的提高的数据库的性能,以至于现在主流的数据库都实现了mvcc。

但是各个数据对于mvcc的实现略有不同:

其中mysql的实现就有undo log,而postgres的实现里面没有undo log.但是postgres里面有clog, clog记录了每一事务的状态。

postgres的每一行的所有的版本是存放一起的,它允许保留aborted事务产生的版本, mysql的最新版本保存在表空间,而历史版本则保存在undo log里面。mysql在事务回滚的时候,应该是同步利用undo log把最新版本的恢复成修改之前的状态,同时删除对应事务产生的undo log,而postgres则是通过异步的vaccum,来把aborted事务产生的历史版本给删除。

mvcc里面最重要的一点就是行可见性判断。这里简单的描述一下postgres的行可见性判断与mysql的行可见性判断。

mysql与postgres都会为每一个事务赋予一个xid,这个xid在数据库内部是单高递增的,它唯一标识了一个事务,同时它定义了数据库中事务相关事件的先后顺序。(这里的事务相关事件主要指begin transaction)

mvcc里面的snapshot读要求每一个事务(或者第一个语句,因为事务隔离级别的不同决定是一个事务一个snapshot还是一个语句一个snapshot)都要有一个snapshot,而mysql与postgres都选择使用当前活动事务的列表来作为snapshot. 每一个事务开始的时候(一个语句开始的时候)获取一下当前整个系统所有已经开始但没有结束的事务的xid.

mysql与postgres对于每一行的每一个版本都记录了两个字段x_min, x_max(mysql不知道叫啥,但是意思应该差不多), x_xmin代表创建这一个版本对应事务的xid, x_max表示删除这个版本对应的事务的xid

判断一个版本是否可见,postgres需要以下几个信息:

当前事务的snapshot(活动事务列表)

clog,可以根据xid来查询当前事务的状态,事务有三个状态pending, committed, aborted

一个版本上的x_min, x_max

首先,postgres先看一下,x_min对应的xid是否在snapshot中能够找到,如果能够找到,说明对应snapshot开始的时候,创建这个版本的事务还没有结束,直接返回该版本不可见

如果x_min在在snapshot里面找不到,说明在取snapshot的时候,创建这一行的事务已经结束,事务结束分两种状态,aborted, committed

通过查询clog,看x_min对应的事务是不是aborted, 如果是aborted, 说明创建这一行的事务已经回滚, 该行不可见

如果事务是committed: 说明创建该行的动作在snapshot之前已经结束,这个时候还需要分情况:

该行的x_max为空,就行是最新的版本,直接返回该行可见

该行有x_max, 但是x_max对应的事务也在snapshot列表里面,说明取snapshot的时候,删除该行的事务还没有结束,该操作对应snapshot不可见,返回该行可见。

该行有x_max, 同时x_max也不在snapshot列表里面,但是x_max对应的clog为aborted, 说明删除操作对应的事务aborted,返回该行可见

该行有x_max, 同时x_max也不在snapshot列表里面,但是x_max对应的clog为committed, 说明删除该行的操作在snapshot之前已经成功,返回该行不可见。

mysql的行可见性应该会简单一点,因为历史版本里面只保存成功提交的版本

行可见性判断的几个参数:对应事务(语句)的snapshot, x_min, x_max

x_min存在于snapshot中,该行不可见

x_min不存在于snapshot中,没有x_max, 该行可见。(该行是最新版本ujn8)

x_min不存在于snapshot中,同时x_max也不存在于snapshot列表中,该行不可见,说明删除操作在snapshot之前已经完成。

什么时候要使用到undo

上面已经提到,undo这个动作发生成rollback一个事务的时候。

同时也发生在数据recovery的时候,因为有些事务正在执行过程中,数据crash了,那么数据库重启做完redo后,要把对应没有提交的事务的动作undo一下。

同时undo log记录历史版本,读历史版本的时候,也要从undo log里面去读。

以上关于mysql的都是自己从互联网上看资料得来的,理解的并不一定正确,后面会根据mysql代码来验证一下。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/121993
推荐阅读
相关标签
  

闽ICP备14008679号