mysql的mvcc原理(多版本并发控制)

前言

RR解决脏读、不可重复读、幻读等问题,使用的是MVCC(Multi-Version Concurrency Control),即多版本的并发控制协议。在了解 MVCC 之前,我们先来聊聊隐藏列、Undo log 和 Read View。

隐藏列

InnoDB中每行数据除了我们创建的字段外还有有隐藏列,其中隐藏列包含了本行数据的事务id、指向undo log的指针等。

Undo log

MVCC 的实现是通过 Undo log 来完成的。当用户读取一行记录时,若该记录已经被其它事务占用,当前事务可以通过 Undo log 读取之前的行版本信息,因为没有事务需要对历史的数据进行修改操作,所以也不需要加锁,以此来实现非锁定读取。

Undo log(回滚日志)可以查看我之前整理的文章-----mysql日志文件总结

Read View

什么是readview

事务(暂记事务1)在某一时刻给事务系统trx_sys打快照,把当时trx_sys状态(包括活跃读写事务数组)记下来,之后的所有读操作根据其事务id(即trx_id)与快照中的trx_sys的状态作比较,以此判断readview对于事务1的可见性。

Read View 中大致包含以下内容:

  1. trx_ids:数据库系统当前活跃事务 ID 集合;
  2. low_limit_id:活跃事务中最大的事务 ID +1;
  3. up_limt_id:活跃事务总最小的事务 ID;
  4. creator_trx_id:创建这个 Read View 的事务 ID。

比如某个事务,创建了 Read View,那么它的 creator_trx_id 就为这个事务的 ID,假如需要访问某一行,假设这一行记录的隐藏事务 ID 为 t_id,那么可能出现的情况如下:

  1.     如果 t_id < up_limt_id,说明这行记录在这些活跃的事务创建之前就已经提交了,那么这一行记录对该事务是可见的。
  2.     如果 t_id >= low_limt_id,说明这行记录在这些活跃的事务开始之后创建的,那么这一行记录对该事物是不可见的。
  3.     如果 up_limit_id <= t_id < low_limit_id,说明这行记录可能是在这些活跃的事务中创建的,如果 t_id 也同时在 trx_ids 中,则说明 t_id 还未提交,那么这一行记录对该事物是不可见的;如果 t_id 不在 trx_ids 中,则说明事务 t_id 已经提交了,那么这一行记录对该事物是可见的。

什么是MVCC

MVCC, 即多版本并发控制。MVCC 的实现,是通过保存数据在某个时间点的快照来实现的,也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。

MVCC举例说明

# 首先开启两个临时客户端,将默认隔离级别改成RC
mysql> set session transaction isolation level READ COMMITTED;
Connection id:    7713
Current database: muke
Query OK, 0 rows affected (0.06 sec)
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set, 1 warning (0.00 sec)

# 客户端1
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
# 首先查看t21 b为4的数据
mysql> select * from t21 where b = 4;
+----+---+---+
| id | a | b |
+----+---+---+
|  4 | 4 | 4 |
+----+---+---+
1 rows in set (0.00 sec)

mysql> update t21 set b = 44 where b = 4;
Query OK, 1 rows affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select sleep(10);
+-----------+
| sleep(10) |
+-----------+
|         0 |
+-----------+
1 row in set (10.01 sec)
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)


# 客户端2 
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t21 where b = 4;
+----+---+---+
| id | a | b |
+----+---+---+
|  4 | 4 | 4 |
+----+---+---+
1 rows in set (0.00 sec)
# 在客户端执行select sleep(10);在执行查询语句
mysql> select * from t21 where b = 4;
+----+---+---+
| id | a | b |
+----+---+---+
|  4 | 4 | 4 |
+----+---+---+
1 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

从上面执行现象可以看出:客户端1的事务先于客户端2的事务执行,但是发现在客户端1休眠的时候,事务2很快就执行完毕并返回了结果。 如果RC模式下读操作需要获取S锁,但是因为当前已经有了X锁,两个锁是互斥的,理论上S锁需要等待X锁释放才会获取,但是并没有发生这种情况,可以看出读操作并没有使用S锁, 而是使用MVCC实现的。

在实验中,客户端2 查询的结果是 客户端1 修改之前的记录,也就是那个点的 Read View,根据上面将的 Read View 原理,被查询行的隐藏事务 ID 就在当前活跃事务 ID 集合中。因此,这一行记录对该事物(客户端2中的事务)是不可见的,可以知道 客户端2 查询的 b=4 记录实际就是来自 Undo log 中。我们看到的现象就是同一条记录在系统中存在了多个版本,这就是多版本并发控制(MVCC)。

图例

扩展知识

  1. RR隔离级别(除了Gap锁(间隙锁)之外)和RC隔离级别的差别是创建snapshot时机不同。 RR隔离级别是在事务开始时刻,确切地说是第一个读操作创建read view的;RC隔离级别是在语句开始时刻创建read view的。
  2. 创建/关闭read view需要持有mutex,会降低系统性能,5.7版本对此进行优化,在事务提交时session会cache只读事务的read view。
  3. 下次创建read view,判断如果是只读事务并且系统的读写事务状态没有发生变化,即trx_sys的max_trx_id没有向前推进,而且没有新的读写事务产生,就可以重用上次的read view。
  4. MVCC 最大的好处是读不加锁,读写不冲突,极大地增加了 MySQL 的并发性。通过 MVCC,保证了事务隔离性。
  5. MVCC 为什么只在 RC 和 RR 两个隔离级别下工作?

        RU: 每次只取最新的值,不存在多个值的情况。 串行:每次查询会加读锁,当有更新时会阻塞住,只有等到查询完锁释放后,才会做更新操作,由此可知RU和串行的隔离级别下,只会存在一个值,不存在多个值的情况。MVCC是解决并发情况下,同时可能产生多个值,从多个值中查询出一个准确值的技术,所以RU,串行是用不到MVCC技术

 

 

学习链接

MySQL的MVCC在各种隔离级别中发挥的作用

MySQL · 源码分析 · InnoDB的read view,回滚段和purge过程简介

深入学习MySQL事务:ACID特性的实现原理

mysql事务-----四种隔离级别

mysql日志文件总结

 

人们以为他们的理性支配言语,偏偏有时反而支配理性。 ---培根

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木子林_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值