从 MySQL 的事务 到 锁机制 再到 MVCC

news2025/1/20 3:51:10

其他系列文章导航

Java基础合集
数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、事务

1.1 含义

1.2 ACID

二、锁机制

2.1 锁分类

2.2 隔离级别

三、MVCC

3.1 介绍

3.2 隔离级别

3.3 原理

四、总结


前言

转眼又一年~~2023马上就要到尾声了,在最后的几天中,我想给大家分享一下 MySQL 的一些小知识。


一、事务

1.1 含义

通俗理解:在我的理解下,事务可以使 一组操作,要么全部成功,要么全部失败。事务其目的是为了下保证数据最终的一致性。

举个例子:举个例子,我给你发支付宝转了666块红包。那自然我的支付宝余额会扣减666块,你的支付宝余额会增加666块。

1.2 ACID

  • 原子性 (Atomicity)
  • 一致性 (Consistency)
  • 隔离性 (lsolation)
  • 持久性 (Durability)

原子性指的是:当前事务的操作要么同时成功,要么同时失败。原子性由undo log日志来保证,因为undo log记载着数据修改前的信息。

比如我们要 insert 一条数据了,那undo log 会记录的一条对应的 delete 日志。我们要 update 一条记录时,那undo log会记录之前的 旧值 的update记录。

如果执行事务过程中出现异常的情况那执行 [回滚]。InnoDB引擎就是利用undo log记录下的数据,来将数据 恢复 到事务开始之前。

隔离性指的是:在事务并发执行时,他们内部的操作不能互相干扰。

如果多个事务可以在同一时刻操作同一份数据,那么就会可能会产生脏读、重复读、幻读的问题。
于是,事务与事务之间需要存在 一定 的隔离。在InnoDB引擎中,定义了四种隔离级别供我们使用:

  • read uncommit(读未提交)
  • read commit (读已提交)
  • repeatable read(可重复复读)
  • serializable (串行) 

不同的隔离级别对事务之间的隔离性是不一样的 (级别越高事务隔离性越好,但性能就越低) ,而隔离性是由MySQL的各种锁来实现的,只是它屏蔽了加锁的细节。

持久性指的就是:一旦提交了事务,它对数据库的改变就应该是永久性的。说白了就是,会将数据持久化在硬盘上。

而持久性由 redo log 日志来保证,当我们要修改数据时,MySQL是先把这条记录所在的页找到,然后把该页加载到内存中,将对应记录进行修改。

为了防止内存修改完了,MySQL就挂掉了(如果内存改完,直接挂掉,那这次的修改相当于就丢失了)。

MySQL引入了 redo log,内存写完了然后会写一份 redo log,这份 redo log 记载着这次在某个页上做了什么修改。

即便 MySQL 在中途挂了,我们还可以根据 redo log来对数据进行恢复。

redo log 是顺序写的,写入速度很快。并且它记录的是物理修改 (xxxx页做了xxx修改),文件的体积很小,恢复速度也很快。

一致性指的就是:我们使用事务的目的 ,而[隔离性][原子性][持久性]均是为了保障 [一致性] 的手段,保证一致性需要由应用程序代码来保证。

比如,如果事务在发生的过程中,出现了异常情况,此时你就得回滚事务,而不是强行提交事务来导致数据不一致。 


二、锁机制

2.1 锁分类

在InnoDB引擎下,按锁的粒度分类,可以简单分为:

  • 行锁
  • 表锁

行锁实际上是作用在索引之上的。

当我们的 SQL 命中了索引,那锁住的就是命中条件内的索引节点(这种就是行锁),如果没有命中索引,那我们锁的就是整个索引树 (表锁)。

简单来说就是:锁住的是整棵树还是某几个节点,完全取决于 SQL 条件是否有命中到对应的索引节点。

而行锁又可以简单分为:

  • 读锁 (共享锁、S锁)
  • 写锁 (排它锁、X锁)

读写锁区别:

  • 读锁是共享的,多个事务可以同时读取同一个资源,但不允许其他事务修改。
  • 写锁是排他的,写锁会阻塞其他的写锁和读锁。

2.2 隔离级别

再回到隔离级别上吧,以例子来说明。

首先来说下read uncommit(读未提交)比如说: A向B转账,A执行了转账语句,但A还没有提交事务,B读取数据发现自己账户钱变多了! B跟A说,我已经收到钱了。A回滚事务[rollback]等B再查看账户的钱时,发现钱并没有多。

简单的定义就是:事务B读取到了事务A还没提交的数据,这种用专业术语来说叫做[脏读]。

对于锁的维度而言,其实就是在read uncommit隔离级别下,读不会加任何锁,而写会加排他锁。读什么锁都不加,这就让排他锁无法排它了。

而我们又知道,对于更新操作而言,InnoDB是肯定会加写锁的 (数据库是不可能允许在同一时间,更新同一条记录的)。而读操作,如果不加任何锁,那就会造成上面的脏读。

脏读在生产环境下肯定是无法接受的,,那如果读加锁的话,那意味着:当更新数据的时,就没办法读取了,这会极大地降低数据库性能。


三、MVCC

3.1 介绍

在MySQL InnoDB引擎层面,又有新的解决方案 (解决加锁后读写性能问题),叫做MVCC(Multi-Version Concurrency Control)多版本并发控制。 

在MVCC下,就可以做到读写不阻塞且避免了类似脏读这样的问题。那MVCC是怎么做的呢?

MVCC通过生成数据快照 (Snapshot)并用这个快照来提供一定级别 (语句级或事务级)的一致性读取。

3.2 隔离级别

回到事务隔离级别下,针对于 read commit (读已提交) 隔离级别,它生成的就是语句级快照,而针对于repeatable read(可重复读),它生成的就是事务级的快照。

前面提到过read uncommit隔离级别下会产生脏读,而read commit (读已提交)隔离级别解决了脏读。

思想其实很简单:在读取的时候生成一个"版本号",等到其他事务commit了之后,才会读取最新已commit的"版本号"数据。

比如说: 事务A读取了记录(生成版本号),事务B修改了记录(此时加了写锁)事务A再读取的时候,是依据最新的版本号来读取的(当事务B执行commit了之后,会生成一个新的版本号),如果事务B还没有commit,那事务A读取的还是之前版本号的数据。

通过[版本]的概念,这样就解决了脏读的问题,而通过 版本,又可以对应快照的数据。

read commit (读已提交) 解决了脏读,但也会有其他并发的问题。 [不可重复读]:一个事务读取到另外一个事务已经提交的数据,也就是说一个事务可以看到其他事务所做的修改。

不可重复读的例子: A查询数据库得到数据,B去修改数据库的数据,导致A多次查询数据库的结果都不一样[危害: A每次查询的结果都是受B的影响的]。

了解MVCC基础之后,就很容易想到repeatable read (可重复复读)隔离级别是怎么避免不可重复读的问题了 (前面也提到了)。

repeatable read (可重复复读)隔离级别是 事务级别]的快照!每次读取的都是厂当前事务的版本],即使当前数据被其他事务修改了(commit),也只会读取当前事务版本的数据。

在InnoDB引擎下的的repeatable read(可重复复读)隔离级别下,在MVCC下快照读,已经解决了幻读的问题 (因为它是读历史版本的数据)。

而如果是当前读 (比如 select * from table for update),则需要配合间隙锁来解决幻读的问题。

剩下的就是serializable (串行)隔离级别了,它的最高的隔离级别,相当于不允许事务的并发,事务与事务之间执行是串行的,它的效率最低,但同时也是最安全的。

3.3 原理

MVCC的主要是通过read view和undo log来实现的。

undo log前面也提到了,它会记录修改数据之前的信息,事务中的原子性就是通过undo log来实现的。所以,有undo log可以帮我们找到 版本]的数据。

而read view 实际上就是在查询时,InnoDB会生成一个read view,read view 有几个重要的字段,看下去就懂了。

  • trx ids (尚未提交commit的事务版本号集合)
  • low limit id (下一次要生成的事务ID值)
  • low limit id (尚未提交版本号的事务ID最小值)
  • creator_trx_id (当前的事务版本号)

在每行数据有两列隐藏的字段,分别是DB TRX ID (记录着当前ID) 以及DB ROLL PTR (指向上一个版本数据在undolog 里的位置指针)。

铺垫到这了,很容易就发现,MVCC其实就是靠[比对版本,来实现读写不阻塞,而版本的数据存在于undo log中。

而针对于不同的隔离级别 (read commit和repeatable read) ,无非就是read commit隔离级别下,每次都获取一个新的1ead view,repeatable read隔离级别则每次事务只获取一个read view


四、总结

事务、锁机制和 MVCC 是数据库管理系统中的三个核心概念,它们协同工作以确保数据的完整性和并发性。

在 MySQL 中,事务提供了一种方法来管理数据库操作的逻辑边界,锁机制用于控制对数据的并发访问,而 MVCC 则通过允许多个事务同时读取数据来提高并发性能。

了解和正确使用这些概念对于数据库管理员和开发人员来说至关重要,以确保数据库应用的性能和可靠性。


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

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

相关文章

关于Python里xlwings库对Excel表格的操作(二十五)

这篇小笔记主要记录如何【如何使用xlwings库的“Chart”类创建一个新图表】。 前面的小笔记已整理成目录,可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 (1)如何安装导入xlwings库; (2…

LeetCode刷题--- 不同路径 III

个人主页:元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 ​​​​​​http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​http://t.csdnimg.cn/hKh2l 前言:这个专栏主要讲述递…

二叉树详解(深度优先遍历、前序,中序,后序、广度优先遍历、二叉树所有节点的个数、叶节点的个数)

目录 一、树概念及结构(了解) 1.1树的概念 1.2树的表示 二、二叉树概念及结构 2.1概念 2.2现实中的二叉树: 2.3数据结构中的二叉树: 2.4特殊的二叉树: 2.5 二叉树的存储结构 2.51 顺序存储: 2.5.2 链式存储&…

Apache Flink连载(二十三):Flink HA - Flink基于Yarn HA

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. Yarn HA配置 ​​​​…

婴幼儿家庭护理百科知识,宝宝健康成长育儿实用课程

一、教程描述 本套教程由具有丰富育儿经验的多名专家精心打造而成,也是专门提供给准爸妈们学习的实用课程,可以解决宝宝的日常护理、日常喂养、饮食调理、疾病防治、意外护理等多方面问题。课程不仅可以丰富你的育儿知识,而且能够让你把这些…

vue写了这么久了你对slot的理解是什么?slot使用场景有哪些?

一、slot是什么 在HTML中 slot 元素 &#xff0c;作为 Web Components 技术套件的一部分&#xff0c;是Web组件内的一个占位符 该占位符可以在后期使用自己的标记语言填充 举个栗子 <template id"element-details-template"><slot name"element-na…

docker应用部署(部署MySql,部署Tomcat,部署Nginx,部署Redis)

Docker 应用部署 一、部署MySQL 搜索mysql镜像 docker search mysql拉取mysql镜像 docker pull mysql:5.6创建容器&#xff0c;设置端口映射、目录映射 # 在/root目录下创建mysql目录用于存储mysql数据信息 mkdir ~/mysql cd ~/mysqldocker run -id \ -p 3307:3306 \ --na…

Plantuml之YAML效果图语法介绍(二十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

3D视觉-3D测量技术对比

从前面四种主流的 3D 测量技术来看&#xff0c;其优点和缺点都很明显&#xff0c;没有单独一种技术可以适用于所有的三维测量场景&#xff0c;从实际应用来看&#xff0c;双目与结构光在人脸识别&#xff0c;拆码垛定位&#xff0c;静态尺寸测量等应用上最为广泛。激光三角法因…

swing快速入门(三十四)输入对话框

&#x1f33c;注释很详细&#xff0c;直接上代码 &#x1f337;新增内容 &#x1f940;字符串输入型 输入对话框用法 &#x1f940;下拉选项输入型输入对话框用法 &#x1fab4;完整代码&#xff1a; package swing31_40;import javax.swing.*; import java.awt.*; import ja…

介绍一款PDF在线工具

PDF是我们日常工作中的一种常见格式&#xff0c;其处理也是我们工作的重要基础性环节&#xff0c;一款可靠的处理工具显得十分重要。 完全免费、易于使用、丰富的PDF处理工具&#xff0c;包括&#xff1a;合并、拆分、压缩、转换、旋转和解锁PDF文件&#xff0c;以及给PDF文件…

网络通信-入门1

网口框架 100M 2. 物理层解读 2.1 同步的方法&#xff1a;编码 为了让接收方在没有外部时钟参考的情况也能确定每一位的起始、结束和中间位置&#xff0c;在传输信号时不直接采用二进制编码。在 10BASE-T 的传输方式中采用曼彻斯特编码&#xff0c;在 100BASE-T 中则采用 4B/…

数字IC设计流程

目录 一、引例——RFID芯片 二、数字IC设计流程的发展史 第一阶段&#xff1a;人工设计 第二阶段&#xff1a;人工为主、计算机为辅 第三阶段&#xff1a;人工与计算机平分秋色 第四阶段&#xff1a;计算机为主、人工辅助 三、目前主流的数字IC设计流程 1、ASIC设计流程…

使用docker轻量化部署snmp agent(SNMPv2访问)

文章目录 服务器环境说明单机部署&#xff08;非挂载conf文件版&#xff09;debian:buster-slim容器简介实现步骤创建Dockerfile创建SNMP配置文件 (snmpd.conf)构建Docker镜像运行Docker容器 注意补充复制容器文件到本地容器、镜像操作 单机部署&#xff08;挂载conf文件版&…

Golang不可不知的7个并发概念

并发性支持是Golang最重要的原生特性之一&#xff0c;本文介绍了Golang中和并发性相关的7个概念。原文: Golang: 7 must-know concurrency related concepts 并发是Go编程语言的基本特性&#xff0c;意味着程序可以同时执行多个任务。Golang的并发独特而强大&#xff0c;其内置…

word中MathType公式编号

直接上效果图&#xff1a; 步骤如下&#xff1a; 安装MathTypeword中安装MathType选项卡。设置MathType选项卡添加分隔符插入公式&#xff0c;自动生成右编码 接下来介绍每一步。 文章目录 1. 安装MathType2. Word中安装MathType选项卡3. 配置MathType选项4. 添加分隔符5. 插…

33--反射

1、反射(Reflection)的概念 1.1 反射的出现背景 Java程序中&#xff0c;所有的对象都有两种类型&#xff1a;编译时类型和运行时类型&#xff0c;而很多时候对象的编译时类型和运行时类型不一致。 Object obj new String("hello"); obj.getClass(); 例如&#xf…

Rust使用gRPC

需要先安装protoc&#xff08;Protocol Buffers Compiler&#xff09;&#xff0c;可据此Protobuf Compiler Installation下载 第一步&#xff1a;创建项目 创建两个新的Rust项目&#xff0c;分别作为服务端与客户端&#xff1a; cargo new rust_grpc_servercargo new rust_grp…

探秘HyperLogLog:Redis中的基数统计黑科技

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 探秘HyperLogLog&#xff1a;Redis中的基数统计黑科技 前言HyperLogLog简介基数和基数统计的重要性HyperLogLog的历史和革命性 HyperLogLog的工作原理哈希函数线性计数与对数计数HyperLogLog的核心算法…

快速上手:探索Spring MVC的学习秘籍!

SpringMVC概述 1&#xff0c;SpringMVC入门案例1.2 案例制作步骤1:创建Maven项目步骤2:补全目录结构步骤3:导入jar包步骤4:创建配置类步骤5:创建Controller类步骤6:使用配置类替换web.xml步骤7:配置Tomcat环境步骤8:启动运行项目步骤9:浏览器访问步骤10:修改Controller返回值解…