一条记录的多幅面孔-事务的隔离级别与 MVCC

一、事务隔离级别

  1. 引出:**事务的隔离性要求,**理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据。我们既想保持事务的 隔离性 ,又想让服务器在处理访问同一数据的多个事务时性能尽量高些舍一部分 隔离性 而取性能者也。
  2. 事务并发执行遇到的问题
    (1)脏写一个事务修改了另一个未提交事务修改过的数据
    (2)脏读一个事务读到了另一个未提交事务修改过的数据
    (3)不可重复读:如果一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事务都能查询得到最新值
    (4)幻读:一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先
    的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来。幻读重点强调了读取到了之前读取没有获取到的记录
  3. SQL标准中的四种隔离级别
    (1)READ UNCOMMITTED :未提交读
    (2)READ COMMITTED :已提交读
    (3)REPEATABLE READ :可重复读
    (4)SERIALIZABLE :可串行化
    各个隔离级别下,允许发生的事务并发下遇到的问题
    在这里插入图片描述
    注意:因为脏写这个问题太严重了,不论是哪种隔离级别,都不允许脏写的情况发生。
  4. MySQL中支持的四种隔离级别
    注意:MySQL在REPEATABLE READ隔离级别下,是可以禁止幻读问题的发生的。与sql标准中规定有出入。MySQL 的默认隔离级别为 REPEATABLE READ(可手动修改)。

二、MVCC原理

  1. 版本链
    前言对于使用 InnoDB 存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列:
    (1)trx_id :每次一个事务对某条聚簇索引记录进行改动时,都会把该事务的 事务id 赋值给 trx_id 隐藏列
    (2)roll_pointer :每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到 undo日志 中,然后这个隐藏
    列就相当于一个指针,可以通过它来找到该记录修改前的信息(找到对应的undo日志)。

    版本连介绍展示如下:在这里插入图片描述在这里插入图片描述
    可以看到,第一张图中的两个事务的sql操作语句,形成了一个版本链(包括最新的记录和undo日志)。每个版本中还包含生成该版本时对应的 事务id
  2. ReadView
    ReadView 中主要包含4个比较重要的内容:
    (1)m_ids :表示在生成 ReadView 时当前系统中活跃的读写事务的 事务id 列表。
    (2)min_trx_id::m_ids 中的最小值。
    (3)max_trx_id:表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。
    (4)creator_trx_id :表示生成该 ReadView 的事务的 事务id 。
    ReadView的作用需要判断一下版本链中的哪个版本是当前事务可见的
  3. ReadView的例子介绍
    (1)在 MySQL 中, READ COMMITTED 和 REPEATABLE READ 隔离级别的的一个非常大的区别就是它们生成ReadView的时机不同
    首先看在 READ COMMITTED 隔离级别下的。在这里插入图片描述

开启二个事务(id=100,200),在id=100的事务中修改名字的值,二个事务均未提交。然后通过查询语句,查询语句执行时候会生成一个ReadView,它的m_ids列表为[100, 200],min_trx_id 为 100 , max_trx_id 为 201 , creator_trx_id 为 0 。那么这次查询到的结果是版本号小于min_trx_id(100)的,所以查到的是 ‘刘备’。
之后提交一下id=100的事务,再次查询时候,会新生成一个ReadView, 它的m_ids列表为[200],min_trx_id 为 200 ,
max_trx_id 为 201 , creator_trx_id 为 0 。那么此时就需要版本号满足小于min_trx_id(200)的才能查询到,所以查到的是’张飞’。
总结一下就是:使用READ COMMITTED隔离级别的事务在每次查询开始时都会生成一个独立的ReadView。

然后再看在 REPEATABLE READ 隔离级别下的。
这个与上一个的区别就是,只会在一个事务中第一次查询建立ReadView,那么对应到上一个修改名字的例子就是,在两个事务均未提交时候,执行查询语句时会生成一个ReadView, 它的m_ids列表为[100, 200],min_trx_id 为 100 , max_trx_id 为 201 , creator_trx_id 为 0 。查询到的是 ‘刘备’。
之后提交一下id=100的事务,再次查询时候,会使用 原来的ReadView,所以查询到的还是 ‘刘备’。这也和这种隔离级别(REPEATABLE READ)很符合(可重复读)。
4. MVCC小结
从上边的描述中我们可以看出来,所谓的 MVCC (Multi-Version Concurrency Control ,多版本并发控制)指的就
是在使用 READ COMMITTD 、 REPEATABLE READ 这两种隔离级别的事务在执行普通的 SEELCT 操作时访问记录的版
本链的过程,这样子可以使不同事务的 读-写 、 写-读 操作并发执行,从而提升系统性能。
READ COMMITTD 、
REPEATABLE READ 这两个隔离级别的一个很大不同就是:生成ReadView的时机不同,READ COMMITTD在每一
次进行普通SELECT操作前都会生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作
前生成一个ReadView,之后的查询操作都重复使用这个ReadView就好了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值