0
点赞
收藏
分享

微信扫一扫

Innodb下的MVCC和隔离级别的联系

数据库的读分为两种

当前读

(读取当前的最新的数据)

更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。

除了 update 语句外,select 语句如果加锁,也是当前读。

select * from t1 for update;(加x锁)

select * from test1.t1 where id=1 lock in share mode;(加s锁)


快照读

(很多场景下,不需要读取最新数据,只要读取快照就可以满足(undo))

不加锁的select语句比如select * from t1 where id =1;

具体读取的数据的版本,和事务隔离级别有关系

在RR隔离级别下,读取到的数据是事务开始的时候的快照数据版本。

在RC隔离级别下,读取到的是事务当前最新的快照数据版本。


session1

session2

begin;

begin;

update t1 set name='aaa' where id=1; 获取x锁



select * from t1;

session1获取x锁后,session2理论上是无法得到x锁和s锁的,也就是无法读取id=1数据,

但是通过一致性非锁定读,读取到了数据。原理:通过MVCC读取的undo里面的快照版本的数据。


MVCC的作用

从上面的实验可以看出,MVCC 就是为了实现读-写冲突不加锁,而这个读指的就是快照读。

InnoDB 在实现 MVCC 时用到的一致性读视图,即 consistent read view,用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现。


RC和RR隔离级别的区别

RC读提交是指,一个事务提交之后,它做的变更才会被其他事务看到。

RR可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。


Read View

在不同的隔离级别下,访问数据时,数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准。

在“可重复读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。

在“读提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的。

这里需要注意的是,“读未提交”隔离级别下直接返回记录上的最新值,没有视图概念;而“串行化”隔离级别下直接用加锁的方式来避免并行访问。


不同隔离级别的实现原理

依赖read view用于隔离级别的实现

(1)什么时候生成Read View

一致性读取(consistent read),根据隔离级别的不同,会在不同的时机建立read view,如下:

RR 事务的第一个select命令发起的时候建立read view,直到事务提交释放

RC 事务的每一个select都会单独建立read view


(2)如何实现多版本

InnoDB 里面每个事务有一个唯一的事务 ID,叫作 transaction id。它是在事务开始的时候向 InnoDB 的事务系统申请的,是按申请顺序严格递增的。

而每行数据也都是有多个版本的。每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的事务 ID,记为 row trx_id。

同时,旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它。也就是说,数据表中的一行记录,其实可能有多个版本 (row),每个版本有自己的 row trx_id。


(3)如何确定Read View是否在该事务可读

RC隔离级别下,每个快照读都会生成并获取最新的Read View,因此可能出现在同一个事务中两次查询的结果不一致的情况。

RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View,之后的快照读获取的都是同一个Read View,之后的查询就不会重复生成了,所以一个事务的查询结果每次都是一样的。



举报

相关推荐

0 条评论