【MySQL进阶之路 | 高级篇】锁的概述以及读写并发问题

news2024/11/14 3:30:11

事务的隔离性是由锁来实现的。

1. 概述

锁是计算机协调多个进程或线程并发访问某一资源的机制。在程序开发中会存在很多线程同步的问题,当多个线程并发访问某个数据的时候,尤其是针对一些敏感的数据(如订单,金额等),我们就需要保证这个数据在任何时刻最多只有一个线程访问,保证数据的完整性和一致性。在开发过程中加锁是为了保证数据的一致性,这个思想在数据库领域同样重要。

在数据库中,除传统的计算资源(如CPU,RAM,I/O等)的争用外,数据也是一种供用户共享的资源。为了保证数据的一致性,需要对并发操作进行控制,因此产生了锁。同时锁机制也为实现MySQL的各个隔离级别分别提供了保证。锁冲突也是影响数据库的并发访问性能的一个重要因素。所以锁对数据库而言显得尤为重要,也会更加复杂。

2. MySQL并发事务访问相同记录

并发事务访问相同记录的情况大致分为三种:读-读,写-写,读-写/写-读。

2.1 读-读情况

读-读情况,即并发事务相继读取相同的记录。读取操作本身不会对记录有任何影响,并不会引起什么问题,所以允许这种情况发生。

2.2 写-写情况

该种情况,即并发事务相继对相同的记录做出改动。

在这种情况下会发生脏写的问题,任何一种隔离级别都不允许这种情况的发生。所以在多个未提交事务相继对一条记录做改动时,需要让它们排队执行,这个排队的过程其实是通过锁来实现的。这个所谓的锁其实是一个内存中的结构,在事务执行前本身是没有锁的,也就是说一开始是没有锁结构和记录进行关联的。如图:

当一个事务想对这条记录做改动时,首先会看看内存中有没有与这条记录关联的锁结构,当没有时就会在内存中生成一个锁结构与之关联。比如,事务T1要对这条记录做改动,就需要生成一个锁结构与之相关。

在锁结构里有很多信息,为了简化理解,只把两个比较重要的属性拿了出来:

  • trx信息:代表这个锁结构是哪个事务生成的。
  • is_waiting:代表当前事务是否在等待。

当事务T1改动了这条记录后,就生成了一个锁结构与该记录关联。因为之前没有别的事务为这条记录加锁,所以is_waiting属性是false,我们把这个场景为称之为获取锁成功,或者加锁成功。然后就可以继续执行操作了。

在事务T1提交之前,另一个事务T2也想对记录做改动,那么先看看有没有锁结构与之关联,发现有个锁结构与之关联后,然后也生成了一个锁结构与这条记录关联,不过锁结构的is_waiting属性值为true,表示当前事务需要等待,我们把这个场景称为获取锁失败,或者加锁失败。如图:

在事务T1提交后,就会把该事务生成的锁结构释放掉,然后看看有没有别的事务在等待获取锁,发现了事务T2还在等待获取锁,所以把事务T2对应的锁结构的is_waiting属性设置为false,然后把该事务对应的线程唤醒,让它继续执行,此时事务T2就算获取到锁了。如图:

小结:

  • 不加锁,意思就是不需要在内存中生成对应的锁结构,可以直接执行操作。
  • 获取锁就是在内存中生成了锁结构,而且锁结构的is_waiting属性为false,也就是事务可以继续执行操作。
  • 获取锁失败,或者加锁失败,或者没有获取到锁,意思就是在内存中生成了对应的锁结构,不过锁结构的is_waiting属性为true,也就是事务需要等待,不可以继续执行操作。

2.3 读-写或写-读情况

读-写或写-读情况,即一个事务进行读取操作,另一个进行改动操作。这种情况可能发生脏读,不可重复读,幻读的问题。

各个数据库厂商对sql标准的支持力度不一样,比如MySQL在REPEATABLE READ隔离级别上已经解决了幻读的问题。

2.4 并发问题的解决方案

怎么解决脏读,不可重复读,幻读这些问题呢?其实有两种可选的解决方案。

方案一:读操作利用多版本并发控制MVCC,写操作进行加锁。、

所谓的MVCC,就是生成一个ReadView,通过ReadView找到符合条件的记录版本(历史版本由undo日志构建)。查询语句只能读到在生成ReadView之前已经提交事务所做的更改,在生成ReadView之前未提交的事务或者之后才开启的事务所做的更改是看不到的。而写操作肯定针对的是最新版本的记录,读记录的历史版本和改动记录的最新版本本身并不冲突,也就是采用了MVCC,读-写操作并不冲突。

普通的select语句在READ COMMITTED和REPEATABLE READ隔离级别下会使用到MVCC读取记录。

  • 在READ COMMITTED隔离级别下,一个事务在执行过程中每次执行select操作时都会生成一个ReadView,ReadView的存在本身就保证了事务不可以读取到未提交的事务所做的更改,也就是避免了脏读现象。
  • 在REPEATABLE READ隔离级别下,一个事务在执行过程中只有第一次执行select操作才会生成一个ReadView,之后的select操作都复用这个ReadView,这样就避免了不可重复读和幻读的问题。

方案2:读-写操作都采用加锁的方式。

如果我们的一些业务场景不允许读取记录的旧版本,而是每次都必须读取记录的最新版本。比如,在银行存款的事务中,你需要先把账户的余额读出来,然后将其加上本次存款的数额,最后再写入数据库中。在将账户余额读取出来后,就不想让别的事务再访问该余额,直到本次存款事务执行完成,其他事务才可以访问账户的余额。这样在读取记录的时候就需要对其进行加锁操作,这样也意味着读操作和写操作也像写写操作那样排队执行。

  • 脏读的产生是因为当前事务读取了另一个未提交的事务写的一条记录。如果另一个事务在写记录的时候就给这条记录加锁,那么当前事务就无法继续读取该记录了,所以也就不会有脏读的问题产生。
  • 不可重复读的产生是因为当前事务先读取一条记录,另一个事务对该记录做了改动后并提交之后,当前事务再次读取时会获得不同的值,如果在当前事务读取记录时就给该记录加锁,那么另一个事务就无法修改该记录,自然也不会发生可重复读。
  • 幻读的问题的产生是因为当前事务读取了一个范围的记录,然后另外的事务向该范围的事务插入了一些新记录,当前事务再次读取该范围的记录的时候发现了新插入的记录。采用加锁的方式解决幻读问题有一定的麻烦,因为当前事务在第一次读取记录时的幻影记录并不存在,所以读取的时候加锁有点尴尬。

一般情况下,我们当然愿意采用MVCC来解决读-写操作并发执行问题,但业务在某些特殊情况下,要求必须采用加锁的方式执行。

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

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

相关文章

面试前端实习常问的关于【ES6新特性】的问题

ES6新特性 日常前端代码开发中,有哪些值得用 ES6 去改进的编程优化或者规范? 常用箭头函数来取代有this指向的函数常用 let 取代 var 命令常用数组/对象的结构赋值来命名变量(结构更清晰,语义更明确,可读性更好)在长字…

基于Delaunay三角网的平面点云面积计算(python)

1、背景介绍 三维点云密度比较高,可以根据点云数据精确计算物体表面面积,如建筑物水平占地面积、室内房间墙面面积等,如下图,这在实际应用中具有非常重要的作用。其实归根到底,计算上述面积,可以认为计算平…

【Linux】基本指令1

文章目录 1. find2. which3. alias4.whereis5.grep6. sort 、uniq7. linux怎么编辑文件中的内容 1. find 1.1 find: 查找文件所在的位置。(当我们进行find搜索的时候,可能需要访问磁盘进而导致效率低下。) 1.2 find / file.txt 在Linux系统是…

掏耳神器哪种最好用?力荐四款优质高口碑产品

要说到掏耳神器,市面上有不少声称能掏掏干净耳垢的挖耳勺。例如棉签、螺旋掏耳勺、可视掏耳勺等。那么那种掏耳神器最好用呢?有着多年采耳经验的我,当然把这三种神器都买来尝试过,很明确地告诉大家,只有可视掏耳勺最好…

Oracle集群RAC磁盘管理命令asmcmd的使用

文章目录 ASM磁盘共享简介ASM磁盘共享的优势ASM磁盘组成ASM磁盘共享的应用场景Asmcmd简介Asmcmd的功能Asmcmd的命令Asmcmd的使用注意事项Asmcmd运行模式交互模式运行非交互模式运行ASMCMD命令分类实例管理命令:文件管理命令:磁盘组管理命令:模板管理命令:文件访问管理命令:…

云计算实训室建设可行性报告

一、建设云计算实训室的目的和意义 随着信息技术的飞速发展,云计算作为一种新型的信息服务模式,已经成为推动信息技术创新和促进信息产业发展的重要力量。中高职院校作为培养高素质技能人才的重要基地,应当紧跟时代步伐,加强云计…

com.mysql.cj.jdbc.Driver 爆红

出现这样的问题就是pom.xml文件中没有添加数据库依赖坐标 添加上这个依赖即可,添加完后重新加载一下Maven即可。 如果感觉对你有用就点个赞!!!

第三十二天 Emmet语法生成HTML标签

前身是zen coding 用缩写提高写代码效率 vscode已经集成该语法 写div直接按tab自动生成<div></div>标签 div*3 再按tab 就可以一下生成四个该标签 父子级的标签 例如ul>li div>span 兄弟关系 divp 生成带类名或者id 输入.as 产生 输入#id 产生 默认是div…

如何用 Python 处理和操作 CSV 文件?

CSV&#xff08;Comma-Separated Values&#xff09;文件是一种常见的数据存储格式&#xff0c;广泛用于数据交换和轻量级数据存储。CSV文件以纯文本格式存储表格数据&#xff0c;每一行代表一条记录&#xff0c;字段之间用逗号&#xff08;或其他分隔符&#xff09;分隔。Pyth…

数据结构(5):树和二叉树

1 树的定义 1.1 树的基本概念 分支可以称为边&#xff0c;结点可以用于存放数据结构。 除了根节点&#xff0c;其他节点只有一个前驱&#xff01;&#xff01;&#xff01;&#xff01; 互不相交也就是 只有一个前驱结点&#xff01; 树应用的很广的 1.2 结点之间的关系 直接…

微服务实践和总结

H5原生组件web Component Web Component 是一种用于构建可复用用户界面组件的技术&#xff0c;开发者可以创建自定义的 HTML 标签&#xff0c;并将其封装为包含逻辑和样式的独立组件&#xff0c;从而在任何 Web 应用中重复使用。 <!DOCTYPE html> <html><head…

Python | Leetcode Python题解之第283题移动零

题目&#xff1a; 题解&#xff1a; class Solution:def moveZeroes(self, nums: List[int]) -> None:n len(nums)left right 0while right < n:if nums[right] ! 0:nums[left], nums[right] nums[right], nums[left]left 1right 1

springboot游戏化教育平台-计算机毕业设计源码92424

游戏化教育平台设计与实现 摘 要 游戏化教育平台是一种融合了游戏元素和教育内容的创新型教育工具&#xff0c;旨在提升学习者的学习兴趣和参与度。本论文基于SpringBoot框架&#xff0c;设计并实现了一款游戏化教育平台。该平台包括用户和管理员两大功能模块。对于用户功能而…

Linux开启coredump

在Linux系统中&#xff0c;C/C程序崩溃是常见的问题之一。Coredump是指当一个程序崩溃时&#xff0c;系统把程序运行时的内存数据以二进制文件的形式保存下来&#xff0c;以便程序开发者进行崩溃分析。本文将介绍如何开启并配置Coredump 1、查看并配置coredump 在Linux系统中…

mac M1安装Roop教程及所遇到的问题

1.安装miniconda&#xff0c;下载地址&#xff1a; 按 Python 版本划分的最新 Miniconda 安装程序链接&#xff1a;https://docs.anaconda.com/miniconda/miniconda-other-installer-links/ 下载后直接默认安装即可。 我用的是&#xff1a;Python3.10对应的Miniconda 2.下载…

在 ArchLinux 上编译运行 axmol 引擎

本文将在 Windows 10 上安装 Arch WSL 中编译 axmol 请确保 WSL2 已正确安装 1. 在微软应用商店安装 ArchLinux 2. 打开 Arch&#xff0c;按照提示输入用户名和密码&#xff0c;尽量简单 3. 配置清华源&#xff0c;速度快的起飞&#xff0c;否则&#xff0c;各种包会安装失败…

C++必修:模拟实现STL之string

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 为了让我们更加深入理解string&#xff0c;接下来我们将模拟实现一个简易版的stri…

力扣高频SQL 50题(基础版)第十七题

文章目录 力扣高频SQL 50题&#xff08;基础版&#xff09;第十七题1075. 项目员工 I题目说明思路分析实现过程准备数据实现方式结果截图 力扣高频SQL 50题&#xff08;基础版&#xff09;第十七题 1075. 项目员工 I 题目说明 项目表 Project&#xff1a; ----------------…

四、GD32 MCU 常见外设介绍 (2) GPIO 模块介绍

2.GPIO 模块介绍 GPIO的全称为通用输入输出口&#xff0c;是很多外设能够正常工作的必要条件。除了一些特定功能的引脚(如电源脚)外&#xff0c;MCU上其他的引脚都可以当做GPIO来使用。本章&#xff0c;我们将对GPIO进行简单介绍&#xff0c;并通过一个“流水灯”的实验来熟悉…

力扣刷题-图论-岛屿类问题-集合实现(c++实现)

我的老师&#xff1a;力扣链接这道题题解中最高赞的回答nettee&#xff0c;从这篇题解中我学到了dfs框架以及解决思路&#xff0c;并独立完成了该题解里的几道习题本人刷题的习惯是学会一个板子&#xff0c;然后之后的同类题都机械的用这个板子去做&#xff0c;最好不做创新&am…