MySQL-MVCC

2022-05-26  本文已影响0人  Zeppelin421

问题

多事务同时访问数据库中的相同数据时

解决方案

概念

MVCC(Multi Version Concurrency Control)即多版本并发控制,是指在数据库中为了实现高并发的数据访问,对数据进行多版本处理,并通过事务的可见性来保证事务能看到自己应该看到的数据版本。

简单说,MVCC多版本并发控制是指:维持一个数据的多个版本,使得读写操作没有冲突,这只是一个理想概念。MySQL 通过快照读实现了 MVCC 理想模型的其中一个具体非阻塞读功能。

实现原理

MySQL 中 MVCC 主要是通过行记录中的隐藏字段、版本链、ReadView来实现的

隐藏字段

MySQL中,在每一行记录中除了自定义的字段,还有一些隐藏字段

版本链

在修改数据的时候,会向 Redo log 中记录修改的页内容(用于恢复数据),也会向 Undo log 中记录数据库原来的快照。Undo log 有两个作用,回滚事务和实现MVCC

事务(trx_id=100)执行了 insert into t_user values(1, '张三', 20);


事务(trx_id=102)执行了update t_user set name = '李四' where id = 1;

事务(trx_id=103)执行了update t_user set name = '王五' where id = 1;

ReadView

多个事务对同一行数据修改后,这行记录除了最新的数据,在 Undo log 中还有多个版本的快照。那其他事务查询时能查到最新版本的数据吗?

ReadView 就是 MVCC 在对数据进行快照时,会产生的一个“读视图

ReadView 中有4个比较重要的变量

ReadView 可见性算法:

当事务对行记录进行快照读时 select * from t_user where id=1;,在版本链的快照中,从最新的一条记录开始,一次判断这4个条件,直到某一版本的快照读对当前事务可见,否则继续比较上一版本的记录

MVCC 只在 RC(解决脏读)和 RR(解决不可重复读)隔离级别下生效。在 RC 隔离级别下,每一次快照读都会生成一个最新的 ReadView;在 RR 隔离级别下,只有事务中第一次快照读会生成 ReadView,之后的快照读都使用第一次生成的 ReadView。

MVCC案例

前提条件:事务(trx_id=100)向表中插入一条记录 insert into t_user values(1, '张三', 20);并提交事务

时间顺序 事务101 事务102 事务103
t1 begin
t2 select * from t_user where id=1;
t3 begin
t4 select * from t_user where id = 1;
t5 begin
t6 select * from t_user where id = 1;
t7 update t_user set name = '李四' where id = 1
t8 select * from t_user where id = 1
t9 select * from t_user where id = 1
t10 commit
t11 select * from t_user where id = 1
t12 update t_user set name = '王五' where id = 1
t13 commit
t14 select * from t_user where id = 1

版本链

在时间点 t1~t6 时,整个版本链中只有一个快照, trx_id = 100


在时间点 t7~t11 时,整个把版本链有两个快照 trx_id = 102、100


在时间点 t12~t14 时,整个把版本链有两个快照 trx_id = 103、102、100

事务隔离级别为RC(读已提交)

当前事务隔离级别为RC时,每个事务每次查询对应生成的 ReadView

事务隔离级别为RR(可重复读)

当前事务隔离级别为RR时,每个事务每次查询对应生成的 ReadView


在 RR 隔离级别下,只有事务中第一次快照读会生成 ReadView,之后的快照读都使用第一次生成的 ReadView,所以 事务101在 t8、t14时刻查询时,使用的 ReadView 跟 t2 时刻一样;事务102在 t9 时刻查询使用 ReadView 跟 t4 时刻一样;事务103在 t11 时刻查询使用的 ReadView 跟 t6 时刻一样。
上一篇 下一篇

猜你喜欢

热点阅读