SQL进阶理论篇(十一):什么是MVCC?

文章目录

  • 简介
  • 什么是MVCC
  • 快照读与当前读
  • 悲观锁的问题示例
  • 参考文献

简介

在MySQL中,默认的隔离级别是可重复读,可以解决脏读和不可重复读的问题,但不能解决幻读问题。如果想要解决幻读问题,就需要采用串行化的方式,通过牺牲数据库的并发事务处理能力,将隔离级别提升到最高。

那有没有一种方式,可以不采用锁机制,而是只通过乐观锁的方式,来解决不可重复度和幻读问题呢?

确实有,MVCC机制就是用来解决这个问题的。在多数情况下,它可以替代行级锁,降低系统的开销(如InnoDB中就是默认开启MVCC机制的,除此之外还有Oracle,DB2是采用多版本读的方式实现隔离级别,但严格来讲不是MVCC)。

大部分的RDBMS都会支持MVCC

本节将主要介绍以下几部分:

  • MVCC机制的思想是什么?
  • 为什么RDBMS要采用MVCC机制,只依靠悲观锁还不够么?

什么是MVCC

MVCC的英文全称是Multiversion Concurrency Control,中文翻译过来就是多版本并发控制系统

顾名思义,MVCC是通过数据行的多个版本管理,来实现数据库的并发控制。

简单的说,它的思想就是保存数据的历史版本。这样我们就可以通过比较版本号来决定数据是否显示出来(具体的规则后面会讲),基于这种乐观锁的机制,我们在读取数据的时候不需要加锁也可以保证事务的隔离性。

先总结一下MVCC的具体作用:

  • 解决了读写之间的阻塞问题。通过MVCC可以让读写之间互相不阻塞,即读的时候不会再阻塞写,反之也是一样,从而提高了事务的并发处理能力;
  • 降低了死锁的概率。MVCC里采用的是乐观锁的思想,所以读取数据时根本不用加锁,即使是写数据的时候,最多也是只锁定必要的行。降低了锁的数量,自然也降低了死锁的概率。
  • 解决一致性读的问题。一致性读又叫做快照读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务的提交结果。

快照读与当前读

快照读,读取的是快照数据,不加锁的select语句都属于快照读,如:

SELECT * FROM player WHERE ...

当前读,读取的是最新数据,而不是历史版本的数据。加锁的select,或者对数据进行增删改查的时候,都会进行当前读。

SELECT * FROM player LOCK IN SHARE MODE;
SELECT * FROM player FOR UPDATE;
INSERT INTO player values ...
DELETE FROM player WHERE ...
UPDATE player SET ...

因此,快照读实际上就是普通读,而当前读包括了加锁的读取和DML操作。

悲观锁的问题示例

接下来,我们以一个具体的例子,来讲解一下采用悲观锁思想可能造成的问题。

比如说,我们有个账户金额表 user_balance,包括三个字段,分别是 username 用户名、balance 余额和 bankcard 卡号。其中只有用户A和用户B有账户余额,其他账户的余额都是0。

接着数据库管理员需要查询这张表里的总账户金额,即执行下面语句:

SELECT SUM(balance) FROM user_balance

这个过程里,用户A或者B自行开启了一个事务,做互相转账。

当管理员事务和用户的事务,时间上撞在一起的时候,会出现什么情况呢?

我们举两个例子(例子均来源于参考文献)。

例子一:由于管理员事务的行级锁的存在,导致用户A给用户B转账会存在等待时间。

如图:

在这里插入图片描述

为了保证数据的一致性,管理员事务在统计数据的时候,会给用到的数据加上行级锁。
比如说用户A所在数据行被加锁之后,用户A就不能再操作自己的记录了,如果想做update,只能等到管理员事务结束后,锁被释放,才能操作。

这就导致了用户A的体验很不好,多了额外的等待时长。

例子二:死锁。

过程如图:

在这里插入图片描述

简单的说,就是管理员在统计的时候,用户B开启了一个事务,给A转账。

管理员事务是一行一行边读边加锁,它先读取用户A的数据,于是持有了用户A数据的行锁,接下来,它应该再读取用户B的数据,再持有用户B数据的行锁。

但是,在它还没有读到用户B的数据之前,用户B就开启了事务,抢先对自己的记录进行了操作,于是用户B持有了自己所在数据行的行锁。

等到管理员事务需要读用户B的数据时,会发现数据行已经被锁上了,咋整,那就只能等呗,于是管理员事务就开始等待用户B数据的锁被释放。

只要用户B的事务正常结束,锁释放,那么管理员事务就能继续加锁,向下执行来完成统计。

但是用户B的事务并没有结束,因为是给用户A转账,因此它还需要update用户A的数据,把多的钱update进去。但问题是用户A的数据已经被管理员事务加锁了,用户B的事务如果想读,该怎么办呢?只能等管理员事务主动释放这个行锁。

于是,场面就变成了,管理员事务在等待用户事务释放B数据的行锁,而用户事务在等待管理员事务释放A数据的行锁,互不相让,死锁了。

这个就是悲观锁的常见问题,不过在基于乐观锁的MVCC里,这种情况发生的概率会很低,具体的我们下节会介绍。

参考文献

  1. 31丨为什么大部分RDBMS都会支持MVCC?

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

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

相关文章

Minio文件服务器(上传文件)

官网:https://www.minio.org.cn/ 开源的分布式对象存储服务器 Window安装 用户名和密码相同 创建bucket,并且将策略改成public 一、添加依赖 二、代码 public class FileUploadTest{public static void main(String[] args) throws Exception{//…

IDA pro软件 如何修改.exe小程序打开对话框显示的文字?

环境: Win10 专业版 IDA pro Version 7.5.201028 .exe小程序 问题描述: IDA pro软件 如何修改.exe小程序打开对话框显示的文字? 解决方案: 一、在IDA Python脚本中编写代码来修改.rdata段中的静态字符串可以使用以下示例代码作为起点(未成功) import idc# 定义要修…

微信小程序背景图片设置

问题 :微信小程序通过css:background-image引入背景图片失败 [渲染层网络层错误] pages/wode/wode.wxss 中的本地资源图片无法通过 WXSS 获取&#xff0c;可以使用网络图片&#xff0c;或者 base64&#xff0c;或者使用<image/>标签 解决方法微信小程序在使用backgroun…

STM32-UART-DMA HAL库缓冲收发

文章目录 1、说明1.1、注意事项&#xff1a;1.2、接收部分1.3、发送部分 2、代码2.1、初始化2.2、缓冲接收2.3、缓冲发送2.4、格式化打印 1、说明 1.1、注意事项&#xff1a; HAL库的DMA底层基本都会默认开启中断使能&#xff0c;如果在STM32CubeMx禁用了中断相关的功能&…

联合电子车载充配电单元全球量产

2023年12月&#xff0c;联合电子新一代车载充配电单元批量交付。该产品将应用于全球市场&#xff0c;可覆盖中国、欧洲、北美、日本的交流与直流充电通讯体系。 该车载充配电单元由车载充电机&#xff08;On-board Charger&#xff09;和高压直流转换器&#xff08;HV DCDC Co…

JVM日常故障排查小结

前置知识 jstack简介 jstack是JVM自带的工具&#xff0c;用于追踪Java进程线程id的堆栈信息、锁信息&#xff0c;或者打印core file&#xff0c;远程调试Java堆栈信息等。 而我们常用的指令则是下面这条: # 打印对应java进程的堆栈信息 jstack [ option ] pid option常见选…

06. Python模块

目录 1、前言 2、什么是模块 3、Python标准库模块 3.1、os模块 3.2、datetime 模块 3.3、random模块 4、自定义模块 4.1、创建和使用 4.2、模块命名空间 4.3、作用域 5、安装第三方依赖 5.1、使用 pip 安装单个依赖 5.2、从 requirements.txt 安装依赖 5.3、安装指…

20231218给Firefly的AIO-3399J【RK3399】开发板刷Android12挖掘机方案

20231218给Firefly的AIO-3399J【RK3399】开发板刷Android12挖掘机方案 2023/12/18 21:07 一、整体编译Rockchip的的Android12的挖掘机方案&#xff01; 由于RK3399的Android12系统默认是IND工业方案&#xff0c;需要修改一下【为挖掘机方案】。 Z:\3TB\81rk_android12_220722\…

三菱plc学习入门(一,认识三菱plc)

今天就开始对三菱的plc软件入一个门&#xff0c;希望小编的文章对读者和初学者有所帮助&#xff01;欢迎评论指正&#xff0c;废话不多说&#xff0c;下面开始学习。 目录 plc的型号介绍 M表示什么&#xff1f; T表示什么&#xff1f; R表示什么&#xff1f; 为什么三菱没…

mysql函数(三)之常见数学函数

MySQL提供了很多常用的数学函数&#xff0c;常见的数学函数及使用如下&#xff1a; ABS(X)&#xff1a;返回X的绝对值。 例子&#xff1a;SELECT ABS(-5); – 结果为5 效果图&#xff1a; CEIL(X)&#xff1a;返回大于或等于X的最小整数值。 例子&#xff1a;SELECT CEIL(3.2…

MyBatis首次使用并查询数据库中表的数据

MyBatis首次使用并查询数据库中表的数据 1、传统Jdbc代码问题分析 public class JdbcTest {public static void main(String[] args) {try {//1.加载数据库驱动Class.forName("com.mysql.jdbc.Driver");//2.创建连接对象String url "jdbc:mysql://192.168.10…

MySQL下载、安装、配置详细教程

目录 1 下载 2 安装 2.1执行安装命令&#xff1a; 2.2 编写配置文件 2.3查看默认mysql的密码&#xff1a; 2.4启动mysql服务 2.5 登录mysql&#xff0c;修改密码 3 系统环境变量配置 3.1 配置 3.2 测试 1 下载 官方网址&#xff1a; https://www.mysql.com/跳转到如…