MVCC多版本并发控制

一、MVCC简介

MVCC(Multi-Version Concurrency Control),即多版本并发控制,在MySQL InnoDB中处理并发时,不加锁和非阻塞并发读,提高并发读性能的一种机制。MVCC维持了数据的多个版本,使得并发读写时没有冲突。

基本概念:

1)当前读:在读取数据时,读取最新版本的数据,为了防止当前数据被其他事务修改,采用加锁的方式,例如共享锁(select lock in mode)、排他锁(select for update)。

2)快照读:在不加锁的情况下,基于MVCC实现的数据读取。因此,快照读的数据不一定是最新版本,也可能是之前的历史版本。

二、MVCC能够解决的问题

数据库并发问题:

1)读读:不存在并发问题

2)读写:存在并发问题,有事务隔离问题,脏读、不可重复读、幻读。

3)写写:有并发问题,可能会造成数据更新丢失。

MVCC不仅可以解决脏读、不可重复读、幻读等问题,还可以提高事务并发性能但不能解决更新丢失问题。

二、MVCC实现原理

MVCC主要依赖于undolog、read view和数据库表中的三个隐藏字段实现。

1.三个隐藏字段

假如我们自定义了一张表,默认会存在三个隐藏字段

MVCC多版本并发控制_第1张图片

2.undolog

回滚日志,在insert、update、delete时产生的记录,用于回滚。

insert的undolog日志,在回滚的时候需要使用到,在事务提交后会被清楚。

update和delete不仅在事务回滚的时候需要,在MVCC快照读取的时候也需要,因此该数据不会轻易删除,只有在事务提交和不涉及快照读后在会由InnoDB的特有线程purpe完成清除。当DB_TRX_ID对于purpe的read view是可见的时候即可完成清除。

不同事务和相同事务对同一条记录的修改,会导致该记录的undolog生成一条记录版本线性表(链表),undolog的链首就是最新的旧版记录,链尾就是最早的旧记录。

3.Read view

事务在进行快照读的时候数据库系统会生成一个快照,记录并且维护当前活跃的未提交的事务ID信息。通过这些信息实现了当前活跃事务对其他事务的可见性。

Read view维护了三个全局属性

trx_list:维护Read view生成时系统正活跃的事务ID,即还未提交的事务

up_limt_id:trx_list中的最小值

low_limit_id:执行当前快照Read view生成时,系统尚未分配的下一个事务Id

判断原则:

当前执行快照前的事务ID = TRX_ID,

如果 TRX_ID < up_limt_id ,则当前事务能看到TRX_ID所在的记录。

如果 TRX_ID > low_limit_id,说明TRX_ID 所在记录是在生成视图之后才出现。

如果  TRX_ID 在trx_list中,说明快照生成时,TRX_ID 事务还在活跃中,TRX_ID 事务是对于正在执行快照的事务来说是看不到的。

二、MVCC执行流程

MVCC多版本并发控制_第2张图片

当多个事务并行时,事务1和事务3处于活跃状态,事务4已提交,事务2此时执行快照读,生成一个试图如下:

MVCC多版本并发控制_第3张图片

在执行快照读的时候当前数据的事务ID是4,因为事务4已经提交。所以:

TRX_ID = 4,显然TRX_ID不在trx_list中,所以TRX_ID对于当前快照事务来说是可见的。因此,事务2读取到的最新数据是事务4所提交的版本。

总结:当多个事务同时并行,每个已经提交的事务数据会被记录在日志文件,还未提交的事务通过快照的方式保存为一个事务ID集合,当前事务想要修改的数据原值是多少无法判断,通过当前数据事务ID和快照事务ID集合判断,如果当前事务ID不在快照事务ID集合中,说明当前事务ID对应的时候已经被提交,在日志文件中可以通过指针找到对应的原值,如果当前事务ID在快照集合中,说明当前事务还未提交,通过指针在日志文件中寻找,必能找到对应的原值。

你可能感兴趣的:(mysql,java)