08 | 快照--MVCC

写在前面:勿以事小而不为,用心做事,把它做好!
一. MVCC
  1. 什么是MVCC?
    MVCC (Multiversion Concurrency Control),即多版本并发控制技术,它使得大部分支持行锁的事务引擎,不再单纯的使用行锁来进行数据库的并发控制,取而代之的是把数据库的行锁与行的多个版本结合起来,只需要很小的开销,就可以实现非锁定读,从而大大提高数据库系统的并发性能
    简化理解:通过数据行的多版本来提升数据库系统的并发性能(一种优化的手段)
    读锁:也叫共享锁、S锁
    写锁:又称排他锁、X锁

  2. 多版本如何理解?
    innodb引擎存储的行数据中包含一些额外的存储信息 DATA_TRX_ID,DATA_ROLL_PTR,DB_ROW_ID,DELETE BIT
    a. 6字节的DATA_TRX_ID 标记了最新更新这条行记录的transaction id
    b. 7字节的DATA_ROLL_PTR 指向当前记录项的rollback segment的undo log记录,找之前版本的数据就是通过这个指针
    c. 6字节的DB_ROW_ID,当由innodb自动产生聚集索引时,聚集索引包括这个DB_ROW_ID的值,否则聚集索引中不包括这个值.,这个用于索引当中
    d. DELETE BIT位用于标识该记录是否被删除,这里的不是真正的删除数据,而是标志出来的删除。真正意义的删除是在commit的时候

  3. innodb引擎中,每个事务都存在一个唯一的transaction id . 它是事务在开启的时候向innodb事务系统申请的,并且按照申请顺序严格递增!
    每次新开启一个事务,通常习惯将之隐喻为一个 '快照’

  4. 数据行存在多个版本,当某个事务更新一行数据的时候,会将该事务的transaction id 赋值给数据行的 DATA_TRX_ID,进而形成一个新的版本!

二. MVCC如何确保事务隔离的可重复读特性?
  1. 可重复读:一个事务在开启的时候可以看到所有已经提交的事务结果,但是在事务执行期间,其他事务更新对它不可见

  2. 在实现上,innodb为每个事务构建一个数组,用来保存这个事务启动瞬间,当前正在活跃的所有事务ID (活跃指的是启动了但还未提交)
    数组里面ID最小值称之为 低水位,最大值加1称之为 高水位,视图数组和高水位组成了当前事务的一致性视图(read-view)

  3. 一个数据版本,对于一个事务视图来说,除了自己的更新总是可见外,有三种情况:
    a. 版本未提交,不可见
    b. 版本已提交,但是是在视图创建后提交的,不可见
    c. 版本已提交,并且是在视图创建前提交的,可见

  4. 什么是当前读?
    a. update更新数据都是先读后写的,而这个读只能是读当前的值,称之为 ‘ 当前读 ’
    b. 除了update外,select语句加锁也是当前读、

mysql> select k from t where id = 1 lock in share mode;  (共享锁)
mysql> select k from t where id = 1 for update;  (排它锁)

三. MVCC实例讲解可重复读
  1. 引出问题
mysql> create table t (
      'id' int(11) not null,
      'k' int(11) default null,
      primary key ('id')
    ) engine = innodb;
insert into t(id,k) values(1,1),(1,2);

在这里插入图片描述
start transaction with consistent snapshot 表示马上开启一个事务,mysql 默认 autocommit = 1;
问题来了:事务A,B,C查询的结果分别为多少?
根据可重复读的隔离级别:事务A的查询结果为1,事务B的查询结果为3

  1. 解剖问题
    我们做出如下假设:
    a. 事务A开始前,系统只存在一个活跃事务ID 是99
    b. 事务A,B,C的版本号分别为100,101,102,且当前系统只存在这4个事务
    c. 三个事务开始前,数据(1,1)的DATA_TRX_ID 为 90

这样,根据上文我们可以得出事务A的视图组为 [99,100],B为 [99,100,101],C为 [99,100,101,102],将上图进行简化:
在这里插入图片描述
d.数据(1,1)最早版本为 (90,1,1)
e.事务C首先更新,版本变为 (102,1,2)
f. 事务B再次更新,版本变为 (101,1,3)
g.因此事务A [99,100]查询数据时候,由于101,102对它不可见,所以事务A查询结果为1,又由于uodate为当前读,所以事务B查询结果为3

上述多数内容借鉴学习有感于:
林晓斌老师mysql实战45讲

https://www.cnblogs.com/chenpingzhao/p/5065316.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值