MySQL:MVCC原理详解

        MySQL是允许多用户同时操作数据库的,那么就会出现多个事务的并发场景。那么再并发场景会出现很多问题:脏读、不可重复读、幻读的问题。

而解决这些问题所用到的方法就是:MVCC 多版本并发控制。而这个MVCC的实现是基于read_view、undoLog

如果不了解这几种问题的概念可以看这两篇博客:

MySQL:事务隔离级别详解,MySQL:三大日志(binlog、redo log、undo log)

1、 reda_view

        read view是一个数据库的内部快照,它记录了数据库在某个时刻的数据信息。read view用于实现事务的隔离性,即在并发事务中,一个事务能看到哪些数据,以及哪些数据对其他事务不可见。read view的生成时机和事务的隔离级别有关,例如,在可重复读隔离级别下,read view会在事务开始时生成,而在读已提交隔离级别下,read view会在每条查询语句执行时生成。

除了记录着数据之外,它还记录着几个变量来辅助我们来判定可见性。

  • min_trx_id:在生成Read View时,当前系统中活跃的读写事务中最小的事务ID,即m_ids中的最小值;
  • max_trx_id:最后开始的事务,该SQL启动时,当前事务链表中最大的事务id编号,也就是最近创建的除自身以外最大事务编号。
  • m_ids:在生成Read View时,当前系统中活跃的读写事务的事务ID列表;
  • creator_trx_id:在生成Read View时,当前事务的事务ID。

 reda_view的判断规则:

  • 如果事务id小于min_trx_id,表示该事务在read view生成之前已经提交,所以对当前事务可见。
  • 如果事务id大于max_trx_id,表示该事务在read view生成之后才开始,所以对当前事务不可见。
  • 如果事务id在min_trx_id和max_trx_id之间,那么需要查看该事务id是否在m_ids中。如果在,表示该事务在read view生成时仍在活跃,所以对当前事务不可见;如果不在,表示该事务在read view生成之前已经提交,所以对当前事务可见。

2、undo log

        MVCC中判断可见性判断的就是下面这个undo log的版本链,假设要查询id为1的记录的姓名,此次事务id(trx_id)为63,那么版本链第一个看到事务id为66,假设此时创建的reda_view中的max_trx_id为65,那就说明名字为小吴的是再此次查询创建reda_view后才进行的修改,所以对此次的查询事务不可见。所以查询出来的应该是小王。

3、MVCC实现 可重复读 和 读已提交

上图再没有使用MVCC版本控制的时候,会出现上面这种问题,再一个事务中读取两次得到的结果不想同,这个就是不可重复读的问题,那么MVCC是只会再第一次查询语句时生成read_View快照,

  1. 事务A第一次查询查出来很正常是“小王”,
  2. 再第二次查询前事务B提交,将小王改为小吴。
  3. 然后事务A进行第二次查询,根据第一次查询时生成的read_View中,根本没有这条记录,则此条记录对A来说是不可见的,所以查询出来的还是小王。

如果是读已提交的隔离级别,则是每执行一次查询语句都会生成reda _View,这样也就能再第二次读的时候生成新的read_View ,然后看到版本链中改成小吴的这条undo log日志了。然后进行可见性判断,此时事务Bid>事务Aid,但又不在活跃事务列表中。说明生成此次快照时,事务B已经提交了,所以条记录对于事务A来说是可见的。

4、幻读的解决

  • 针对快照读(普通 select 语句),可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。
  • 针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/439976.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【基础算法练习】Trie 树

文章目录 模板题:[ACwing 835. Trie字符串统计](https://www.acwing.com/problem/content/description/837/)题目描述代码与解题思路 模板题:[ACwing 143. 最大异或对](https://www.acwing.com/problem/content/145/)题目描述代码与解题思路 Trie 算法需…

搭建 prometheus + grafana + springboot3 监控

下载安装包 下载prometheus:https://github.com/prometheus/prometheus/releases/download/v2.42.0/prometheus-2.42.0.windows-amd64.zip 下载grafana: https://dl.grafana.com/enterprise/release/grafana-enterprise-9.4.1.windows-amd64.zip Spr…

面向云服务的GaussDB全密态数据库

前言 全密态数据库,顾名思义与大家所理解的流数据库、图数据库一样,就是专门处理密文数据的数据库系统。数据以加密形态存储在数据库服务器中,数据库支持对密文数据的检索与计算,而与查询任务相关的词法解析、语法解析、执行计划生…

FL Studio21.2.2中文完整版 适合专业创作者

FL Studio 简称FL,全称:Fruity Loops Studio,因此国人习惯叫它"水果"。目前版本是FL Studio2024,它让你的计算机就像是全功能的录音室,大混音盘,非常先进的制作工具,让你的音乐突破想…

Mysql 更新数据

MySQL中使用UPDATE语句更新表中的记录,可以更新特定的行或者同时更新所有的行。基本语法结构如下: UPDATE table_name SET column_name1 value1,column_name2 value2,……, column_namen valuen WHERE(condition); column_name1,column_name2,……,…

npm login 错误 no credentials to set

如果你在使用如下npm命令时遇到了报错: npm login npm adduser报错如下: npm login err! no credentials to set. 如果你的报错信息正好类似,并且npm 版本大于9.0.0,那么只要重新安装低于9.0.0 版本的npm即可解决这问题 目前…

Django框架(三)编写第一个Django应用程序——第二部分

目录 编写第一个Django应用程序,第二部分 数据库设置 创建模型(Model) 激活模型 使用API Django Admin 简介 创建管理员用户 启动开发服务器 进入管理站点 将投票应用程序加入管理站点 探索管理功能 编写第一个Django应用程序&…

elk之简介

写在前面 本文看下es的简介。 1:简介 背后公司,elastic,08年纽交所上市,与腾讯,阿里等云厂商有合作,推出云产品,类似功能的产品由solr,splunk,但使用量es当前遥遥领先…

【Java反序列化】Shiro-550漏洞分析笔记

目录 前言 一、漏洞原理 二、Shiro环境搭建 三、Shiro-550漏洞分析 解密分析 加密分析 四、URLDNS 链 前言 shiro-550反序列化漏洞大约在2016年就被披露了,在上学时期也分析过,最近在学CC链时有用到这个漏洞,重新分析下并做个笔记&…

负载均衡技术助力企业数字化转型和高可用架构实现

文章目录 什么是高可用架构什么是负载均衡负载均衡设备硬件负载均衡的代表产品软件负载均衡的代表产品 负载均衡基于OSI模型分层负载均衡在网络层负载均衡在传输层负载均衡在应用层 优先考虑负载均衡的场景硬件负载均衡的缺点云负载均衡正在成为最佳选择企业数字化转型对负载均…

[PHP]严格类型

PHP: 类型声明 - Manual

大模型学习与实践笔记(十四)

使用 OpenCompass 评测 InternLM2-Chat-7B 模型使用 LMDeploy 0.2.0 部署后在 C-Eval 数据集上的性能 步骤1:下载internLM2-Chat-7B 模型,并进行挂载 以下命令将internlm2-7b模型挂载到当前目录下: ln -s /share/model_repos/internlm2-7b/ ./ 步骤2&…