【MySQL】事务、隔离级别、MVVC是怎么回事?
【MySQL】事务、隔离级别、MVVC是怎么回事?
一、认识事务
1、为什么要设计事务
事务会把数据库从一种一致状态转换为另一种一致状态。
2、事务的四个特征
- 原子性
- 事务是不可分割的工作单位
- 一致性
- 事务从一种状态转变为下一种一致的状态。提交或者回滚,不可以破坏原来的表结构。
- 隔离性
- 通过锁、MVVC来实现
- 持久性
- 事务一旦提交,结果就是永久性的,即使发生当即。数据库也能将数据恢复。
3、事务的分类
- 扁平事务
- 带有保存点的扁平事务
- 链事务
- 嵌套事务
- 分布式事务
二、事务的实现
事务的隔离性由锁来实现。而原子性、一致性、持久性通过数据库的redo log和undo log来完成。
redo log称为重做日志,用来保证事务的原子性和持久性。
undo log用来保证事务的一致性。
redo恢复提交事务修改的页操作,而undo回滚行记录到某个特定版本。redo通常是物理日志,记录的是页的物理修改操作,undo是逻辑日志,根据每行记录进行记录。
1、redo log
重做日志用来实现事务的持久性,其有两部分组成:
- 一是内存中的重做日志缓冲(redo log buffer),其是易失的
- 二是重做日志文件(redo log file),其是持久的
InnoDB是事务的存储引擎,其通过Force Log at Commit机制实现事务的持久性,即当事务提交(Commit)时,必须先将该事务的所有日志写入到重做日志文件进行持久化,待事务的Commit操作完成才算完成。
特点:
- redo log用来保证事务的持久性,undo log用来帮助事务回滚及MVCC的功能。
2、undo log
重做日志记录了事务的行为,可以很好地通过其对页进行“重做”操作。但是事务有时候还需要进行回滚操作,这时就需要undo。
因此在对数据库进行修改时,InnoDB存储引擎不但会产生redo,还会产生一定量的undo。如果用户执行的事务或者语句由于某种原因失败了,又或者用户用一条ROLLBACK语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子。
除了回滚,undo log另外一个作用就是MVCC。当用户读取一行记录的时候,若该记录已经被其他事务所占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取。
三、MVCC如何实现事务的隔离性?
1、认识MVCC
2、案例引入
事务A和B的时序关系如下图,那么在B提交之后,A能否看到B事务修改的值呢?
答案是不同隔离级别下快照数据不同,根据可见性算法来判断。
四、MVCC的组成部分
1、第一部分:隐藏字段
在InnoDB引擎中,每一行记录上都会包含几个用户不可见的字段,如上图所示。隐藏主键指的是如果在创建表的时候没有主键索引,那么就根据非空的列创建索引,如果没有非空的列,那么InnoDB通过隐藏的Row_ID来创建一个隐藏的主键索引。
回滚指针
假设现在有一行数据,事务1添加进来的,其结构如下。
2、第二部分:undo log
假设现在来了一个事务2,对上面的行执行修改操作,整个过程如下图
再来一个事务3
- 当不同的事务对同一条记录做修改的时候,会导致该记录的undolog形成一个线性表,也就是链表,链表的链首是最新的历史记录,而链尾是最早的历史记录。
问题:如果现在有了事务4,那么事务4读取到的是哪一个版本的数据?
答案:在上面的事务123演示的过程中,并没有提到事务是否提交,事务开启的时机。那么事务4读取哪个版本数据,一定有相应的规则。
3、第三部分:readview
事务在进行快照读的时候会产生读视图
案例演示
问当前快照读能否读取到刚刚修改的记录值
根据下面的可见性算法分析,可以得出结论