MySQL-MVCC:概述、工作原理、readView实现快照读、数据库解决问题、MVCC无法防止超卖

MySQL-MVCC:概述、工作原理、readView实现快照读、数据库解决问题、MVCC无法防止超卖

      • 一、概述
      • 二、MVCC工作原理
      • 三、readView实现快照读
      • 四、MVCC 可以为数据库解决什么问题
      • 五、MVCC无法防止超卖

一、概述

多版本并发控制(Multi-Version Concurrency Control,简称MVCC)是一种数据库管理系统中广泛采用的并发控制机制,尤其在MySQL的InnoDB存储引擎中得到了广泛应用。MVCC主要是为了实现事务处理的并发性,同时确保事务间的隔离性,从而避免脏读、不可重复读以及幻读等问题,而这些是ACID原则中的隔离性所要求的

二、MVCC工作原理

1、隐藏列维护版本信息

InnoDB为每行记录添加了额外的隐藏列来支持MVCC主要包括两个与事务相关的列

  • DB_TRX_ID(也称为创建版本号):记录的是最近修改该行数据的事务ID。
  • DB_ROLL_PTR(删除版本号或回滚指针):指向该行数据在回滚段(Undo Logs)中的undo记录。

2、快照读与当前读

  • 快照读(Snapshot Read):这是MVCC的核心概念非锁定读操作(如SELECT)默认情况下会看到一个历史版本的数据视图,即在事务开始时已经提交的所有数据版本
  • 当前读(Current Read):对某一行进行加锁的操作,如SELECT ... FOR UPDATE或SELECT ... LOCK IN SHARE MODE,以及INSERT、UPDATE和DELETE操作,都会获取最新版本的数据,并可能阻塞其他事务对该行的访问

3、版本链与可见性判断

​ MVCC通过检查事务ID和系统版本号(每个事务都有一个系统版本号,可以理解为事务的“时间戳”)来决定某个事务能否看到某一行的版本。具体来说,当一个事务执行查询时,HeapTupleSatisfiesMVCC这样的函数会被调用来判断某一行对于当前事务是否可见

  • 如果DB_TRX_ID小于等于当前事务的系统版本号,那么这一行是可见的,因为它是早于当前事务开始前就已经提交的。
  • 如果DB_TRX_ID大于当前事务的系统版本号,但该事务ID对应的事务已提交,则检查undo日志来找到合适的可见版本。
  • 若事务ID对应未提交的事务或者找不到有效的undo日志,则该行不可见。

实际案例:
假设在MySQL的InnoDB存储引擎下,有两个并发的事务A和B,它们都处于可重复读(Repeatable Read)隔离级别

  • 事务A首先开始并执行了一个SELECT查询,此时它获得了一个数据快照。
  • 然后事务B开始,并更新了一行数据,提交了事务。
  • 此时,即使事务B已经改变了那行数据,事务A再次执行相同的SELECT查询时,由于MVCC的作用,它仍然会看到第一次查询时的数据版本,而不是事务B更新后的版本。

通过这种方式,MVCC实现了不同事务之间对同一行数据的不同版本的并发访问,增强了系统的并发性能,同时保证了事务的隔离性

三、readView实现快照读

​ MVCC(多版本并发控制)中的ReadView用来在并发环境下为事务提供一致性读视图的重要机制。MySQL的InnoDB存储引擎在可重复读(Repeatable Read)隔离级别下,通过ReadView来确保一个事务在其整个生命周期内看到的数据是一致的。
ReadView原理概述:
事务开始执行查询时,在可重复读隔离级别下会生成一个ReadView。这个ReadView包含以下关键信息:

  • creator_trx_id创建当前ReadView的事务ID

  • trx_ids生成ReadView时刻系统中活跃的所有读写事务的事务ID列表

  • up_limit_id活跃事务中最小的事务ID,通常是一个**“未提交阈值”**,小于这个ID的事务是已经提交完成的事务

  • low_limit_id下一个要分配给新事务的ID,即系统中最大的事务ID值,大于这个ID的事务一定是尚未启动或在生成ReadView后才启动的事务

判断某一行记录对于当前事务是否可见时,ReadView遵循如下规则

  • 如果行的DB_TRX_ID(事务ID)小于等于up_limit_id且不包含在trx_ids列表中,则该行对于当前事务是可见的,因为它是由之前已经提交的事务修改的
  • 如果行的DB_TRX_ID大于up_limit_id,则认为是不可见的,因为这是由后续创建的新事务修改的
  • 对于存在于trx_ids列表中的事务ID,如果与creator_trx_id相同,表示是当前事务自身对数据的修改,也是可见的;否则,由于这些事务在ReadView生成时尚未提交,所以该行对当前事务是不可见的

案例说明
假设在一个电商场景中,存在两个并发事务T1和T2,并且数据库设置的是可重复读隔离级别。

  • 事务T1首先开始并读取商品A的库存数量为10。
  • 同一时刻,事务T2也读取商品A的库存,并将库存减少到8,但此时还未提交。
  • 事务T1进入支付流程,需要再次确认库存。
  • 在此过程中,InnoDB为事务T1生成了一个ReadView,它包含了T2的事务ID,因为T2正在活跃但未提交。
  • 当事务T1再次尝试读取商品A的库存时,由于ReadView的作用,它不会看到T2尚未提交的更改,因此仍能看到库存为10,从而避免了因并发带来的数据不一致问题。

总结来说,ReadView通过维护不同事务间的版本关系确保每个事务看到的都是一个固定的历史版本集合,从而实现了在并发环境下的可重复读特性

四、MVCC 可以为数据库解决什么问题

​ MVCC(Multi-Version Concurrency Control,多版本并发控制)在数据库系统中主要用于解决以下问题:
1、并发访问冲突
​ 在高并发的数据库环境中,多个事务可能同时对同一数据行进行读写操作。如果没有合适的并发控制机制,可能会导致数据的一致性问题
MVCC通过为每个事务提供一个“快照”视图使得不同事务可以基于各自看到的不同版本的数据执行操作,从而减少因锁定造成的阻塞和等待

2、事务隔离级别下的异常现象

  • 脏读(Dirty Read):一个事务读取到了另一个未提交事务修改的数据。MVCC确保了事务只能读取到已经提交的数据版本,避免了脏读问题。

  • 不可重复读(Non-Repeatable Read):在一个事务内,两次执行相同的查询语句却得到不同的结果,因为在这两个查询之间,其他事务修改并提交了该数据。在可重复读(Repeatable Read)隔离级别下,MVCC通过保持事务开始时的数据快照来防止这种情况发生。

  • 幻读(Phantom Read):在一个事务中,同样的查询条件,在事务执行过程中由于其他事务插入新的行而导致前后查询结果集不一致。MVCC结合间隙锁(Next-Key Locks)在MySQL的InnoDB存储引擎RR隔离级别下有效解决了幻读问题。

实际案例:
案例一

假设在电商场景中,有两个并发的事务分别代表两个用户购买同一件商品的操作。

  • 事务A首先读取商品库存信息,然后进入支付流程但尚未完成提交。

  • 事务B在同一时间也读取了该商品库存,并成功完成购买和提交。

  • 如果没有MVCC,事务A继续完成支付后尝试扣减库存时可能会引发数据一致性问题;而有了MVCC,事务A只能看到自己开启事务时的商品库存状态,但是无法保证不会出现超卖情况

案例二

在银行账户转账场景中,用户A从自己的账户转账给用户B。

  • 假设事务1代表A查看自己的账户余额,此时事务还未开始转账操作。
  • 事务2是另一并发请求,将一笔资金存入A的账户并已提交。
  • 如果使用的是支持MVCC的数据库,当事务1开始执行转账操作时,它仍然会基于最初查看的账户余额来进行计算,而不是新到账的资金,这样就避免了不可重复读的问题,但是无法保证余额<0的情况

总结来说,MVCC通过对数据行创建多个版本,并根据事务的启动时间和可见性规则,有效地维护了事务间的隔离性,提高了系统的并发性能,并降低了死锁的发生概率

五、MVCC无法防止超卖

​ 即使在数据库中使用了MVCC(多版本并发控制),秒杀或者库存扣减等场景下仍然可能由于并发问题导致超卖现象。MVCC可以解决读操作的并发冲突,但在写操作密集且需要严格保证数据一致性的场景下,仅依靠MVCC机制并不足以防止超卖。
​ 在库存扣减的场景中,多个事务同时尝试扣减同一件商品的库存时,如果都基于同一初始库存值进行扣减,并最终提交事务,就有可能造成实际售出的商品数量超过库存总量,即出现超卖情况。
避免库存超卖,通常需要结合以下策略

  • 悲观锁:对要更新的库存记录加行级排他锁,确保在同一时刻只有一个事务能执行扣减库存的操作。

  • 乐观锁

    • 使用UPDATE ... WHERE inventory > 0 AND version = current_version的语句,其中version是一个用于乐观锁控制的字段,在每次更新前先检查该字段值是否与预期一致,若不一致则说明有其他事务已修改过库存,本次更新失败
    • InnoDB引擎中,虽然MVCC主要用于并发读取优化,但可以通过配合使用SELECT … FOR UPDATE来实现类似乐观锁的效果,锁定查询到的数据行,阻止其他事务在此期间对其进行修改。
  • 分布式锁:在分布式环境下,还可以通过Redis、ZooKeeper等中间件实现分布式锁,确保全局范围内库存扣减的原子性和一致性。

  • 队列处理:将所有的购买请求放入一个消息队列,然后由后台服务按照顺序逐个处理扣减库存,这样也可以避免并发带来的超卖问题。

  • 预扣减库存:在用户点击购买按钮时,直接根据预计的订单量一次性扣除库存,然后再进入支付环节,一旦支付失败再恢复库存,这种做法简单粗暴,但可能会牺牲一定的用户体验和系统复杂度。

综上所述,虽然MVCC有助于提高并发读取性能并降低死锁,但它并不能完全解决高并发场景下的库存超卖问题,还需要结合其他的并发控制策略来确保库存扣减的正确性

MySQL-MVCC:概述、工作原理、readView实现快照读、数据库解决问题、MVCC无法防止超卖 到此完结,笔者归纳、创作不易,大佬们给个3连再起飞吧

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

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

相关文章

无法使用debugger,debugger在项目中不生效,导致无法有效排查问题

debugger是浏览器提供的调试语句&#xff0c;其主要是通过停止JS的执行&#xff0c;相当于设置断点。它的使用方法很简单&#xff0c; 只需要在我们的JS语句中&#xff0c; 插入一行debugger; 即可。 在JS代码编写的过程中&#xff0c;我们都会通过浏览器的调试模式&#xff08…

微擎安装,卡在“安装微擎”界面

进入install.php&#xff0c;点击【在线安装】 下一步配置数据库&#xff0c;开始安装系统 然后显示进度条&#xff0c;进度条一闪而过 然后就没有进度条显示了&#xff0c;一直卡在这里 第一次等了好久&#xff0c; 删除目录下的文件&#xff0c;重装还是这样 再重启服务器&…

代码随想录算法训练营第三十九天|LeetCode62 不同路径、LeetCode63 不同路径II

62.不同路径 思路&#xff1a;确定dp数组及其下标含义&#xff0c;dp[i][j]代表到达i&#xff0c;j坐标的路径数。确定递推公式dp[i][j] dp[i-1][j]dp[i][j-1]。因为只能向右向下移动。初始化dp数组&#xff0c;dp数组的第一行第一列都为1&#xff0c;因为不能向上向左。遍历…

3D-Genome | Hi-C互作矩阵归一化指南

Hi-C 是一种基于测序的方法&#xff0c;用于分析全基因组染色质互作。它已广泛应用于研究各种生物学问题&#xff0c;如基因调控、染色质结构、基因组组装等。Hi-C 实验涉及一系列生物化学反应&#xff0c;可能会在输出中引入噪声。随后的数据分析也会产生影响最终输出噪声&…

Python Tkinter GUI 基本概念

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;如果停止&#xff0c;就是低谷&#xf…

PostgreSQL教程(二十五):服务器管理(七)之管理数据库

每个正在运行的PostgreSQL服务器实例都管理着一个或多个数据库。因此&#xff0c;在组织SQL对象&#xff08;“数据库对象”&#xff09;的层次中&#xff0c;数据库位于最顶层。本章描述数据库的属性&#xff0c;以及如何创建、管理、删除它们。 一、概述 一个数据库是一些S…

计算机网络概论01

计算机系统基础知识 基本组成 计算机系统由硬件和软件组成。 硬件由五大部分&#xff0c;他们分别是&#xff1a; 运算器 执行算数运算和逻辑运算控制器 控制cpu的工作&#xff0c;决定了计算机运行过程的自动化。包括指令控制逻辑、时序控制逻辑、总线控制逻辑和中断控制逻辑…

node项目通过.env文件配置环境变量

https://www.npmjs.com/package/dotenv require(dotenv).config()console.log(process.env, process.env.apiKeyOnServer)我开发的chatgpt项目&#xff1a; https://chat.xutongbao.top

Linux驱动适配内核时,对于不同版本内核中有变化函数的处理

一、情景 Linux驱动适配不同内核时&#xff0c;由于内核版本的不同&#xff0c;有些函数可能没有&#xff0c;或者函数直接变化了&#xff0c;高版本可能增加了一些参数。 二、常规处理方案&#xff0c;根据内核版本判断 一般情况我们处理方式是在使用这些函数时&#xff0c…

Imagination:RISC-V CPU的重要力量

根据SHD集团最近发布的报告显示&#xff0c;RISC-V正全速发展中。通过分析从2021年到2030年这十年间RISC-V核在不同应用和功能领域的潜在市场&#xff0c;作者Rich Wawrzyniak得出结论称&#xff0c;到2030年&#xff0c;22.3%的SoC将包含RISC-V CPU&#xff0c;RISC-V的收入预…

Docker网络+原理+link+自定义网络

目录 一、理解Docker网络 1.1 运行tomcat容器 1.2 查看容器内部网络地址 1.3 测试连通性 二、原理 2.1 查看网卡信息 2.2 再启动一个容器测试网卡 2.3 测试tomcat01 和tomcat02是否可以ping通 2.4 只要删除容器&#xff0c;对应网桥一对就没了 2.5 结论 三、…

蓝牙耳机潜水时可以用吗?适合潜水的四大游泳耳机分享

在科技日新月异的今天&#xff0c;我们越来越依赖各种电子设备来丰富我们的生活。无论是运动、工作还是休闲娱乐&#xff0c;耳机都成为了我们不可或缺的伙伴之一。然而&#xff0c;当谈到水上活动时&#xff0c;许多人可能会对蓝牙耳机是否能在水下使用感到困惑。虽然市面上有…

前端实现图片绕指定圆心转动,且图片自身不转动的功能

前端实现图片绕指定圆心转动&#xff0c;且图片自身不转动的功能、 div>img div: 利用css的animation 去做循环 用transform: rotate 去做旋转 然后利用transform-origin: bottom left;指定旋转圆心位置 img 在div旋转的同时 做反向旋转 <template><div class&qu…

SpringBoot第三课-日志

1.日志分类 2.默认使用 默认使用logback与slf4j作为底层默认日志 但是由于日志是系统启动就需要使用&#xff0c;所以与其他的自动配置不同&#xff0c;自动配置是后来使用的&#xff0c;而日志是使用监听器配置好的。 ApplicationListener 3.日志级别 1.级别介绍 SpringB…

刷题第11天

代码随想录刷题第11天 | 二叉树前中后序遍历 前序遍历 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x…

学AI,3种人,3种学法

在刘润的文章《都说要学AI&#xff0c;但3种人&#xff0c;3种学法》中&#xff0c;作者针对当前AI热潮下不同人群的学习需求&#xff0c;提出了三种不同的学习策略&#xff0c;觉得很有启发性&#xff0c;重点总结如下&#xff0c;原始文章较长&#xff0c;链接在文章结尾。 随…

使用采购管理软件构建更高效的采购模式

采购流程是企业整个采购部门的关键要素。无论企业规模大小&#xff0c;构建采购流程的模式都将直接影响企业控制成本、管理风险和保持流程弹性的能力。 下面我们将解释采购模式的类型、优缺点&#xff0c;以及如何确定哪种模式最适合你的采购部门。 集中采购的优缺点 在集中采…

Windows的自动更新和自带的杀毒软件怎么弄掉!

关闭Windows系统更新 Windows系统更新是为了保持设备的平稳和安全运行,保持操作系统安全、稳定及获取新功能修复已知问题并修补安全漏洞的重要过程。如果您想要临时或永久关闭Windows系统的自动更新,可以采用以下几种方式。不过,请务必意识到,禁用系统更新可能会导致您的系…

什么是VRRP?

目录 什么是VRRP&#xff1f; 一、VRRP的定义 VRRP的三种状态 VRRP决定哪个路由器是Master。 二、VRRP的作用 三、VRRP名词解释 1、Virtual Router 2、VRRP Router 四、华为VRRP实验配置基础 检查基于IPv4的VRRP基本功能配置结果 随着网络的快速普及和相关应用的日益深…

Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验(三)

Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验&#xff08;前导&#xff09; Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验&#xff08;一&#xff09; Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验&#xff08;二&#xff09; 八、板级验证 1.验证内容 通过电脑…