写点什么

MySQL,MVCC 详解,快照读在 RC、RR 下的区别

作者:乌龟哥哥
  • 2022 年 6 月 29 日
  • 本文字数:1606 字

    阅读完需:约 5 分钟

一、什么是 MVCC

我们在操作数据库的时候总是这四大类 读读 读写 写读 写写,读读肯定是没有任务数据问题的,但对事物有了解的同学就会知道,读写、写写操作很容易就会导致数据不一致。


在此之前解决这类问题的常用方式就是加锁,听名字就知道这是个很复杂、很耗性能的操作,所以大神们不满足这个操作,从而在 MySQL 里面实现了 MVCC。


MVCC 并不是 MySQL 独有的,它是一个理念,百度百科解释如下


Multi-Version Concurrency Control 多版本并发控制,MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程语言中实现事务内存。


MVCC 里面有一些关键词,理解这些关键词,你就明白了什么是 MVCC。MVCC 是解决读写、写读导致数据不一致的问题,写写问题还是需要加锁来解决。


所以我们可以使用 MVCC + 锁(乐观锁/悲观锁)来解决全部的问题。

二、当前读、快照读

当前读就是读取最新的数据,为了保证读取的是最新且准确的数据,所以它在读取的时候会加锁,防止其它事物操作。


快照读是不加锁的方式,当一个事物要操作数据库的时候,会在这个事物的基础上形成一个快照,其它的操作就读取这个快照。


MVCC 就是基于快照读来实现的,在 MySQL 里面的快照读是基于这样几个关键点来实现的


  • 三个隐藏参数 (DB_ROW_ID 隐藏主键 id、DB_ROLL_PTR 回滚指针、DB_TRX_ID 事物 id)

  • undo log 日志

  • read view

三、隐藏字段

假如我们有一张表,里面有两个字段,name、age,但实际上我们表里的数据是这样的


3-1、隐藏主键

6byte,隐含的自增 ID(隐藏主键),如果数据表没有主键,InnoDB 会自动以 DB_ROW_ID 产生一个聚簇索引


聚簇索引:数据存储和索引是存在一起的,逻辑上和物理上都是一起的,一个表只能有一个聚簇索引。


注:理解聚簇索引可以很好的理解 MySQL 的索引规则,感兴趣的可以看看这个 MySQL索引详解

3-2、事物 id

记录这条记录最后一次操作的事物 id

3-3、回滚指针

回滚指针,指向这条记录的上一个版本(存储于 rollback segment 里),用于配合下面的 undo log。

四、undo log

undo log 日志分为两种


  • insert undo log 数据库在插入数据的时候产生,只有在当前事物回滚的时候才有用,所以在当前事物结束的时候它就没用了,就会被删除。

  • update undo log 数据库在更新、删除的时候产生,除了当前事物会使用,在快照读的时候也会使用,所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除


假设我们的隐藏主键是从 1、2、3…, 事物主键、回滚指针也是这样生成的 (事实上不是这样的规则),那么我们对上面的表进行操作,将会形成如下的链式结构。


插入数据



修改张三为李四



修改年纪为 25



注:这里的指针是指向这条数据,而不是里面的 主键。

五、Read View

什么是读视图呢?数据库的操作都是多个事物同时进行的,有读有写。假如当前有两个事物,A 事物读取,B 事物正在更新数据。


在 A 事物开始的时候,就形成当前数据库的一个快照,记录并维护系统当前活跃事务的 ID。read view 主要是用来做可见性判断的,它会判断每条记录的的数据,这条数据可能是真实的数据,也可能是 undo log 中的数据。


read view 用一个可见性的算法,来判断当前是读取真实的数据,还是 undo log 的数据。这里可以简单理解 read view 内部维护了一个事物 id 列表,里面有最大值和最小值,可以判断其它事物的 id 是否在这个可见范围内。

N、其它

N-1、快照读在 RC 和 RR 下的区别

  • RC (read-committed)读已提交, 可能会导致 不可重复读、幻读

  • RR (repeatable-read)可重复读,可能会导致 不可重复读


幻读 : 事物 A 查询数据库查询出来了 20 条数据,然后事物 B 删除了 2 条数据,这时候事物 A 再去查询发现只有 18 条了,从而产生了幻觉。


我们知道在 RR 级别下面不会产生幻读,之所以不会产生幻读,是快照读在 RC 和 RR 下的生成的策略不一样。


RC 隔离级别下,是每个快照读都会生成并获取最新的 Read View;而在 RR 隔离级别下,则是同一个事务中的第一个快照读才会创建 Read View, 之后的快照读获取的都是同一个 Read View。

发布于: 刚刚阅读数: 3
用户头像

乌龟哥哥

关注

正在努力寻找offer的大四小菜鸟 2021.03.16 加入

擅长 Hbuilder、VS Code、MyEclipse、AppServ、PS 等软件的安装与卸载 精通 Html、CSS、JavaScript、jQuery、Java 等单词的拼写 熟悉 Windows、Linux、 等系统的开关机 看–时间过得多快,不说了,去搬砖了

评论

发布
暂无评论
MySQL,MVCC详解,快照读在RC、RR下的区别_6月月更_乌龟哥哥_InfoQ写作社区