MySql,MVCC实现及其机制,快照读在RC,RR下的区别说明

 更新时间:2024年04月08日 08:50:35   作者:今吴霜.  
这篇文章主要介绍了MySql,MVCC实现及其机制,快照读在RC,RR下的区别说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

一、什么是MVCC

多版本并发控制

Multiversion Concurrency Control

大部分的MySQL的存储 引擎,比如InnoDB,Falcon,以及PBXT并不是简简单单的使用行锁机制。它们都使用了行锁结合一种提高并发的技术,被称为MVCC(多版本并 发控制)。MVCC并不单单应用在MySQL中,其他的数据库如Oracle,PostgreSQL,以及其他数据库也使用这个技术。 

MVCC避免了许多需要加锁的情形以及降低消耗。这取决于它实现的方式,它允许非阻塞读取,在写的操作的时候阻塞必要的记录

MVCC保存了某一时刻数据的一个快照。意思就是无论事物运行了多久,它们都能看到一致的数据。也就是说在相同的时间下,不同的事物看相同表的数据是不同的。如果你从来没有这方面的经验,可能说这些有点令人困惑。但是在以后这个会很容易理解和熟悉的。

每个存储引擎实现MVCC方式都是不同的。有许多种包含了乐观(optimistic)和悲观(pessimistic)的并发控制。我们用简单的InnoDb的行为来举例说明MVCC工作方式。

InnoDB实现MVCC的方法是,它存储了每一行的两个额外的隐藏字段,这两个隐藏字段分别记录了行的创建的时间和删除的时间。在每个事件发生的时 候,每行存储版本号,而不是存储事件实际发生的时间。每次事物的开始这个版本号都会增加。自记录时间开始,每个事物都会保存记录的系统版本号。依照事物的 版本来检查每行的版本号。在事物隔离级别为可重复读的情况下,来看看怎样应用它。

SELECT

  • InnoDB检查每行,要确定它符合两个标准。
  • InnoDB必须知道行的版本号,这个行的版本号至少要和事物版本号一样的老。(也就是是说它的版本号可能少于或者和事物版本号相同)。这个既能确定事物开始之前行是存在的,也能确定事物创建或修改了这行。
  • 行的删除操作的版本一定是未定义的或者大于事物的版本号。确定了事物开始之前,行没有被删除。
  • 符合了以上两点。会返回查询结果。

INSERT

  • InnoDB记录了当前新增行的系统版本号。

DELETE

  • InnoDB记录的删除行的系统版本号作为行的删除ID。

UPDATE

  • InnoDB复制了一行。这个新行的版本号使用了系统版本号。它也把系统版本号作为了删除行的版本。

所有其他记录的结果保存是,从未获得锁的查询。这样它们查询的数据就会尽可能的快。要确定查询行要遵循这些标准。缺点是存储引擎要为每一行存储更多的数据,检查行的时候要做更多的处理以及其他内部的一些操作。

MVCC只能在可重复读和可提交读的隔离级别下生效。不可提交读不能使用它的原因是不能读取符合事物版本的行版本。它们总是读取最新的行版本。可序列化不能使用MVCC的原因是,它总是要锁定行。

下面的表说明了在MySQL中不同锁的模式以及并发级别。

在这里插入图片描述

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

在此之前解决这类问题的常用方式就是 加锁,听名字就知道这是个很复杂、很耗性能的操作,所以大神们不满足这个操作,从而在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 日志分为两种

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

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

五、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。

MySQL/InnoDB定义的4种隔离级别:

Read Uncommited

  • 可以读取未提交记录。

Read Committed (RC)

  • 针对当前读,RC隔离级别保证对读取到的记录加锁 (记录锁),存在幻读现象

Repeatable Read (RR)(默认)

  • 针对当前读,RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。

Serializable

  • 从MVCC并发控制退化为基于锁的并发控制。不区别快照读与当前读,所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。
  • Serializable隔离级别下,读写冲突,因此并发度急剧下降,在MySQL/InnoDB下不建议使用。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持程序员之家。

相关文章

  • mysql使用SQLyog导入csv数据不成功的解决方法

    mysql使用SQLyog导入csv数据不成功的解决方法

    给mysql导入数据,选中某个表选择导入--导入使用本地csv数据即可,单有的时候不知道什么问题导入不成功
    2014-07-07
  • 比较详细的MySQL字段类型说明

    比较详细的MySQL字段类型说明

    MySQL支持大量的列类型,它可以被分为3类:数字类型、日期和时间类型以及字符串(字符)类型。本节首先给出可用类型的一个概述,并且总结每个列类型的存储需求,然后提供每个类中的类型性质的更详细的描述。概述有意简化,更详细的说明应该考虑到有关特定列类型的附加信息,例如你能为其指定值的允许格式。
    2008-08-08
  • MySQL使用explain命令查看与分析索引的使用情况

    MySQL使用explain命令查看与分析索引的使用情况

    这篇文章主要介绍了MySQL使用explain命令查看与分析索引的使用情况,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • 深入理解MySQL数据类型的选择优化

    深入理解MySQL数据类型的选择优化

    这篇文章主要介绍了深入理解MySQL数据类型的选择优化,MySQL数据类型是定义列中可以存储什么数据以及该数据实际怎样存储的基本规则,正确的选择数据库字段的字段类型对于数据库性能有很大的影响
    2022-08-08
  • mysql通过文档读取并执行命令之快速为mysql添加多用户和数据库技巧

    mysql通过文档读取并执行命令之快速为mysql添加多用户和数据库技巧

    这篇文章主要介绍了mysql通过文档读取并执行命令之快速为mysql添加多用户和数据库技巧的相关资料,需要的朋友可以参考下
    2015-09-09
  • mysql单字段多值分割和合并的处理方法

    mysql单字段多值分割和合并的处理方法

    这篇文章主要给大家介绍了关于mysql单字段多值分割和合并的处理方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • MySQL高可用架构之MHA架构全解

    MySQL高可用架构之MHA架构全解

    MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了 automating master failover 功能,本文重点给大家介绍MySQL高可用架构之MHA架构全解,感兴趣的朋友一起看看吧
    2021-07-07
  • mysql常用日期时间/数值函数详解(必看)

    mysql常用日期时间/数值函数详解(必看)

    下面小编就为大家带来一篇mysql常用日期时间/数值函数详解(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • MySQL利用UNION连接2个查询排序失效详解

    MySQL利用UNION连接2个查询排序失效详解

    这篇文章主要给大家介绍了关于MySQL利用UNION连接2个查询排序失效的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用MySQL具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • Ubuntu?服务器安装?MySQL?远程数据库的方法

    Ubuntu?服务器安装?MySQL?远程数据库的方法

    本篇介绍如何在 Linux 服务器上安装 MySQL 数据库,并设置为可远程连接,本文通过命令给大家介绍的非常详细,对Ubuntu?安装?MySQL远程数据库感兴趣的朋友一起看看吧
    2022-08-08

最新评论

?


http://www.vxiaotou.com