超全MySQL锁机制介绍
前言
MySQL作为关系型数据库管理系统中的佼佼者,为了保证数据的一致性和完整性,在并发控制方面采用了锁机制。锁机制是数据库管理系统用于控制对共享资源的访问,避免多个事务同时修改同一数据造成的数据不一致问题。了解MySQL的锁机制对于数据库管理员和开发人员来说都是至关重要的。本文将详细介绍MySQL的锁机制,包括其概念、分类、使用场景以及在实际编程中的应用。
一、MySQL锁机制概念
MySQL的锁机制是为了保证事务的隔离性,通过锁定数据库资源来防止多个事务并发执行时导致数据不一致。锁可以分为共享锁和排他锁两种类型,共享锁允许多个事务读取同一资源,而排他锁则阻止其他事务访问已锁定的资源。
二、MySQL锁的分类
1、从性能上分类:
-
行锁:锁定表中的某一行或多行记录,其他事务不能修改被锁定的行,但可以同时读取或修改其他行。行锁粒度较小,并发度高,但加锁开销较大。
-
表锁:锁定整张表,阻止其他事务对该表进行写操作(但可能允许读操作,具体取决于锁的类型)。表锁粒度大,开销小,但并发度低。
2、从对数据操作的粒度分类:
-
全局锁:锁住整个Database,由MySQL的SQL layer层实现;
-
表锁:锁住某个表,由MySQL的SQL layer层实现;
-
页锁:在页的粒度上进行锁定,锁定的数据资源比行锁要多,因为一个页中有多个行记录;
-
间隙锁:锁的是两个值之间的空隙,间隙锁是在可重复读隔离级别下才会生效;
-
行锁:锁某一数据Row的索引,也可锁定行索引之间的间隙(即间隙锁),由存储引擎实现;
3、从对数据库操作的类型分类:
-
读锁:又叫共享锁,针对同一份数据,多个读操作可以同时进行而不会互相影响;
-
写锁:当前写操作没有完成前,它会阻断其他写锁和读锁,数据修改操作都会加写锁,查询也可以通过for update加写锁;
-
意向锁:又称I锁,针对表锁,主要是为了提高加表锁的效率,是MySQL数据库自己加的。当有事务给表的数据行加了共享锁或排他锁,同时会给表设置一个标识,代表已经有行锁了,其他事务要想对表加表锁时,就不必逐行判断有没有行锁可能跟表锁冲突了,直接读这个标识就可以确定自己该不该加表锁。
三、锁详解
1. 行锁
行锁是MySQL中最细粒度的锁,它仅对表中的某一行记录进行加锁。当事务需要对某行记录进行修改时,会先对该行记录加行锁,其他事务在行锁释放前无法修改该行记录,但可以同时读取或修改其他行记录。
使用场景:高并发、更新操作频繁的场景。
特点:行锁提高了并发性能,但可能增加锁的开销,因为需要更频繁地加锁和解锁。
实现原理:行锁通常基于索引实现。只有在使用索引条件检索数据时,MySQL才会使用行级锁。
SQL示例:
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 FOR UPDATE; -- 对id为1的行加行锁
-- 进行修改操作
COMMIT; -- 提交事务,释放行锁
2. 表锁
表锁是对整个表加锁,阻止其他事务对该表进行写操作(可能允许读操作,取决于锁的类型)。表锁的开销较小,但并发度低,因为它会阻塞其他事务对整个表的访问。
使用场景:通常用于MyISAM存储引擎,或者在只需要读取整个表而不需要频繁更新的场景下使用。
特点:表锁的开销小、加锁快,但并发度最低,因为它锁定整个表,容易发生锁冲突。
LOCK TABLES table_name WRITE; -- 对表加写锁
-- 进行修改操作
UNLOCK TABLES; -- 释放锁
3. 全局锁
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML、DDL语句,已经更新操作的事务提交语句都将被阻塞
应用场景:做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。如果不加全局锁,先后执行数据备份和业务的数据更新操作,会导致数据不一致
使用全局锁进行数据库逻辑备份的过程:
-
加全局锁
flush tables with read lock;
mysqldump是数据库用于数据备份的工具,执行数据备份。
注意:mysqldump是MySQL提供的一个工具,不是sql语句,需要在windows命令行中执行
mysqldump -uroot -p123456 user>user.sql
在加锁后,DML和DDL被阻塞,其他客户端不能写入数据,但是DQL可以执行,其他客户端可以查找数据
备份结束,得到备份后的文件,释放锁
unlock tables;
4. 页锁
只有BDB存储引擎支持页锁,页锁就是在页的粒度上进行锁定,锁定的数据资源比行锁要多,因为一个页中可以有多个行记录。当我们使用页锁的时候,会出现数据浪费的现象,但这样的浪费最多也就是一个页上的数据行。页锁的开销介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁和行锁之间,并发度一般。
5. 间隙锁
间隙锁是MySQL中用来保证事务的并发性和一致性的锁机制。它的作用是锁定记录间的间隙,防止其他事务在间隙中插入或删除记录,从而避免了脏读和不可重复读等问题的出现。间隙锁是在访问索引时产生的,它会锁住索引中的区间范围,而不是具体的记录。当一个事务在访问索引时,如果发现索引中的某个间隙没有被锁定,则会产生间隙锁,锁定该间隙。当其他事务尝试在同一个间隙中插入或删除记录时,会被阻塞,直到持有间隙锁的事务提交或回滚。间隙锁主要解决了幻读的问题,特别是在InnoDB存储引擎的可重复读事务隔离级别下。
6. 共享锁(S锁)
共享锁又称读锁,允许多个事务对同一资源加共享锁进行并发读操作,但加共享锁的事务不能修改数据。
使用场景:多个事务需要同时读取同一数据,而不需要修改的场景。
SQL示例:
SELECT * FROM table_name LOCK IN SHARE MODE; -- 对查询结果加共享锁
7. 排他锁(X锁)
排他锁又称写锁,它阻止其他事务对已锁定资源进行读写操作。当一个事务对某行记录加排他锁进行修改时,其他事务无法访问该行,直到排他锁释放。
使用场景:需要对数据进行修改,且要求修改期间数据不被其他事务访问的场景。
SQL示例:SELECT ... FOR UPDATE实际上就是对所选行加排他锁。
8. 意向锁
意向锁是InnoDB为了支持多粒度锁定而自动加的锁。当事务想要在行上加共享锁或排他锁时,它首先必须在表级别获得相应的意向锁。意向锁表明事务希望在行上加锁,但并不会阻止其他事务对表进行加锁操作。
意向锁是隐式的,不需要用户显式加锁,它分为意向共享锁(IS锁)和意向排他锁(IX锁)。
SQL示例:意向锁是InnoDB内部自动处理的,不需要用户通过SQL语句来显式请求。当执行如SELECT ... FOR UPDATE或SELECT ... LOCK IN SHARE MODE等操作时,InnoDB会自动在相应的表上加意向锁。
四、锁的升级
锁的升级是指,在并发事务执行过程中,当某个事务无法满足当前所需的锁级别时,系统会自动将该事务的锁级别升级为更高级别的锁。这通常是为了保证数据的一致性和并发性能。
在MySQL中,锁升级主要发生在以下情况:
当某个事务需要获取的是行级锁,但由于并发冲突或其他原因无法满足事务的要求时,系统会将该事务的锁级别升级为表级锁。
当某个事务操作的对象不符合行锁加锁规则,比如没有走索引或非唯一索引记录数达到一定数量,系统也会将该事务的锁级别升级为表级锁。
合理的索引设计、适当的事务隔离级别设置可以帮助减少锁升级的发生,从而提高并发性能和系统吞吐量。
五、锁的重新请求
锁的重新请求通常发生在以下情况:当一个事务在持有锁的状态下,需要再次访问已经被其他事务锁定的资源时,该事务会重新请求锁。这种情况下,系统会根据当前的锁情况和策略来决定是否授予该事务新的锁。
在实际应用中,锁的重新请求可能会因为锁等待、锁冲突等原因而失败,导致事务被阻塞或回滚。因此,在编写数据库应用时,需要合理设计事务的逻辑,避免长时间持有锁,以减少锁冲突和提高系统的并发性能。
需要注意的是,无论是锁的升级还是锁的重新请求,都需要在数据库管理系统(DBMS)的控制下进行,以确保数据的一致性和完整性。同时,开发人员也需要了解并遵循DBMS的锁机制规则,以编写出高效、稳定的数据库应用。
六、可能出现的问题及解决方案
在实际应用中,可能会遇到死锁、锁等待超时等问题。死锁是指两个或多个事务相互等待对方释放资源,导致都无法继续执行。解决死锁的方法包括调整事务的执行顺序、使用超时设置等。锁等待超时通常发生在高并发场景下,当某个事务长时间持有锁不放时,其他事务会因为等待锁而超时。解决这类问题可以通过优化查询语句、减少锁的持有时间、增加锁等待超时时间等方式。
查看死锁
使用SHOW ENGINE INNODB STATUS命令:
这个命令提供了关于InnoDB存储引擎的详细状态信息,其中也包含了最近的死锁信息。你可以运行这个命令,然后查找LATEST DETECTED DEADLOCK部分来查看死锁的详细信息。
在输出中,查找LATEST DETECTED DEADLOCK部分,它会显示导致死锁的SQL语句以及事务的详细信息。
2. 查看information_schema数据库:
information_schema数据库中的INNODB_LOCKS和INNODB_LOCK_WAITS表也包含了关于InnoDB锁的信息。你可以查询这些表来获取当前锁的状态和等待情况。
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;
处理死锁
1. 超时设置:
你可以通过设置事务的超时时间来避免长时间等待。如果事务在指定的时间内无法获得所需的锁,它将自动回滚,从而避免死锁。
2. 优化查询和索引:
很多时候,死锁是由于不恰当的查询或缺少索引导致的。优化查询语句,确保它们能够高效地使用索引,可以减少锁的竞争和死锁的可能性。
3. 调整锁的顺序:
如果两个事务尝试以不同的顺序锁定资源,它们可能会发生死锁。尝试调整事务中锁定资源的顺序,使它们以相同的顺序进行,可以减少死锁的风险。
4. 使用低隔离级别:
在某些情况下,降低事务的隔离级别可以减少锁的需求,从而降低死锁的可能性。但请注意,这可能会增加其他并发问题(如脏读或不可重复读)的风险。
5. 避免大事务:
大事务通常持有锁的时间更长,增加了与其他事务发生死锁的机会。尽量将大事务拆分成多个小事务,以减少锁的持有时间。
6. 分析并重构代码:
在某些情况下,死锁可能是由于应用程序的逻辑错误导致的。仔细分析代码,确保事务的逻辑正确,并避免在事务中执行不必要的操作。
7. 使用第三方工具:
有些第三方工具可以帮助你监控和管理MySQL中的锁和死锁情况。这些工具可以提供更详细的信息和建议,帮助你更有效地处理死锁问题。
总之,处理MySQL中的死锁需要综合考虑多个方面,包括查询优化、索引设计、事务管理以及应用程序逻辑等。通过合理的配置和优化,你可以减少死锁的发生,提高数据库的性能和稳定性。
结语
了解MySQL中的锁机制对于数据库管理员和开发人员来说至关重要,它能帮助我们更好地控制并发访问,确保数据的一致性和完整性。通过合理使用不同的锁类型,我们可以提高系统的并发性能,减少锁冲突和死锁等问题。在实际应用中,需要根据具体的业务场景和需求选择合适的锁策略,并关注可能出现的问题,采取相应的优化措施。
相关文章:

超全MySQL锁机制介绍
前言 MySQL作为关系型数据库管理系统中的佼佼者,为了保证数据的一致性和完整性,在并发控制方面采用了锁机制。锁机制是数据库管理系统用于控制对共享资源的访问,避免多个事务同时修改同一数据造成的数据不一致问题。了解MySQL的锁机制对于数…...

【CV】计算机视觉中的特征追踪与背景处理
计算机视觉领域中的重要任务之一是视频特征追踪,它可以用于目标跟踪、运动分析、行为识别等应用。然而,在实际应用中,经常会遇到需要仅处理视频中特定特征物体而忽略背景的情况,这就需要进行背景处理。本文将介绍如何使用Python和…...

CAPL如何实现TLS握手认证
CAPL有专门的章节介绍如何实现TLS握手认证的函数: CAPL调用哪些函数实现TLS握手认证,需要了解TLS在整个通信过程的哪个阶段。 首先TCP需要建立连接,这是TLS握手的前提。当TLS握手认证完成后,可以传输数据。 所以TLS握手开始前需要确保TCP建立连接,TCP传输数据前需要确保…...

Linux -- 日志
一 日志的重要性 在之前的编程经历中,如果我们的程序运行出现了问题,都是通过 标准输出 或 标准错误 将 错误信息 直接输出到屏幕上,以此来排除程序中的错误。 这在我们以往所写的程序中使用没啥问题,但如果出错的是一个不断在运行…...

WebRtc 视频通话,语音通话实现方案
先了解一下流程 和 流程图(chatGpt的回答) 实现 (底层代码实现, 可作为demo熟悉) 小demo <template><div><video ref"localVideo" autoplay muted></video> <!-- 本地视频元素,用于显示本地视频 --><video ref"r…...

IndyTcpServer使用详解
1、IndyTCPserver的创建 IdTCPServer1.DefaultPort:= 8000; IdTCPServer1.ListenQueue:= 1024; //同时处理请求队列数限制 IdTCPServer1.MaxConnections:= 1024; //同时连接数量限制,为0不限制连接数 IdTCPServer1.ContextClass:= TNewIdServerContext; //设置为自定义TIdSe…...

pytest + yaml 框架 - 参数化读取文件路径优化
针对小伙伴提出参数化时读取外部文件,在项目根路径运行没问题,但是进入到项目下子文件夹运行用例,就会找不到文件问题做了优化。 关于参数化读取外部文件相关内容参考前面这篇pytest yaml 框架 -25.参数化数据支持读取外部文件txt/csv/json/…...

C++:多态-重写和重载
重写(Override)和重载(Overload)是面向对象编程中常用的两个概念,它们虽然都涉及到方法的定义,但是在实现和使用上有着不同的特点。 重写(Override): 重写是指在子类中重…...

element ui的table多选
使用el-table的selection-change事件来获取选中的值; 例: html代码: <el-button type"primary" click"openTableSet">列表设置</el-button><!-- 列表设置弹框 --> <el-dialog :close-on-click-mo…...

python基础---基础运算
基础运算 可以使用type获取一个变量的类型 常见的数据类型 整形, 可以存储任意大小的整数, 支持二进制(如0b100,换算成十进制是4)、八进制(如0o100,换算成十进制是64)、十进制(100)…...
【数学】泰勒公式
目录 引言 一、泰勒公式 1.泰勒公式及推导 (1)推导 (2)公式 2.泰勒中值定理 (1)定理1(佩亚诺余项) (2)定理2(拉格朗日余项) …...

C++基础-编程练习题及答案
文章目录 前言一、查找“支撑数”二、数组元素的查找三、爬楼梯四、数字交换五、找高于平均分的人 前言 C基础-编程练习题和答案 一、查找“支撑数” 【试题描述】 在已知一组整数中, 有这样一种数非常怪, 它们不在第一个, 也不在最后一个&…...

eNSP-抓包解析HTTP、FTP、DNS协议
一、环境搭建 1.http服务器搭建 2.FTP服务器搭建 3.DNS服务器搭建 二、抓包 三、http协议 1.HTTP协议,建立在TCP协议之上 2.http请求 3.http响应 请求响应报文参考:https://it-chengzi.blog.csdn.net/article/details/113809803 4.浏览器开发者工具抓包…...

【栈】Leetcode 验证栈序列
题目讲解 946. 验证栈序列 算法讲解 在这里就只需要模拟一下这个栈的出栈顺序即可:使用一个stack,每次让pushed里面的元素入栈,如果当前栈顶的元素等于poped容器中的当前元素,因此就需要让栈顶元素出栈,poped的遍历…...

【数据库原理及应用】期末复习汇总高校期末真题试卷08
试卷 一、选择题(每题 2 分,共 30 分) 1. ___ ____是长期存储在计算机内的有组织,可共享的数据集合. A.数据库管理系统 B.数据库系统 C.数据库 D.文件组织 2. 数据库类型是按照 来划分…...

每天五分钟深度学习:数学中的极值
本文重点 在数学领域中,极值是一个极其重要的概念,它不仅在纯数学理论研究中占据核心地位,而且在工程、物理、经济等实际应用领域也发挥着不可替代的作用。极值问题涉及函数的最大值和最小值,是微积分学中的一个基本问题。本文旨在详细介绍数学中的极值概念、性质、求解方…...

【Linux】Linux——Centos7安装Tomcat
1.下载Tomcat 安装包 官网地址:Apache Tomcat - Apache Tomcat 9 Software Downloadshttps://tomcat.apache.org/download-90.cgi 2.将下载的安装包上传到 Xftp 上,我是直接放到 usr 下了 3.将安装包解压到 /usr/local/ tar -zxvf apache-tomcat-9.0.8…...

SpringBoot+vue实现右侧登录昵称展示
目录 1. 定义User数据 1.1.在created方法获取数据 1.2.头部导航栏绑定User数据 1.3.在data中定义User数据 2. 获取数据 2.1.接收父组件传递的值 2.2.展示数据 3. 页面效果 在SpringBoot和 Vue.js 结合的项目中实现右侧登录昵称展示,通常涉及到前端的用户界面…...

【网络原理】UDP协议 | UDP报文格式 | 校验和 | UDP的特点 | 应用层的自定义格式
文章目录 一、UDP协议1.UDP的传输流程发送方接收方 2.UDP协议报文格式:长度受限校验和如何校验:CRC算法:循环冗余算法md5算法: 2.UDP的特点 二、开发中常见的自定义格式1.xml(古老)2.json(最流行…...

NodeJs入门知识
**************************************************************************************************************************************************************************** 1、配置Node.js与npm下载(精力所致,必有精品) …...

代码随想录学习Day 34
62.不同路径 题目链接 讲解链接 动归五部曲: 1.确定dp数组及其下标的含义:dp[i][j]的含义是从(0, 0)走到(i, j)所需的步数; 2.确定递推公式:因为只能往右或者往下,所以dp[i][j] dp[i - 1][j] dp[i][j - 1]。 3.…...

由于找不到MSVCP120D.dll,无法继续执行代码。重新安装程序可能会解决此问题
由于找不到MSVCP120D.dll,无法继续执行代码。重新安装程序可能会解决此问题 一、问题详细描述二、问题产生背景三、问题原因四、解决办法1、安装缺少的库2、直接更换更高版本的opencv 五、vs版本对应vc1、版本对应2、vs对应vc查看方法 一、问题详细描述 同样可能会报 ÿ…...

【前端】输入时字符跳动动画实现
输入时字符跳动动画实现 在前端开发中,为了提升用户体验,我们经常需要为用户的交互行为提供即时的反馈。这不仅让用户知道他们的操作有了响应,还可以让整个界面看起来更加生动、有趣。本文将通过一个简单的例子讲解如何实现在用户输入字符时…...

C语言面试重点问题
1. 冒泡排序法 2. strlen、strcpy、strcat、strcmp的用法和原理 3. 大小端的区分 3.1 主函数区分大小端 #include <stdio.h>int main(void) {int num 0x11223344;char *p (char *)#if (0x11 *p){printf("大端!\n");}else if (0x44 *p){printf(…...

antlr4略解
文章目录 1. antlr4是用来干什么的?2. 什么是lexer和parser?3. 使用antlr4生成某语言的lexer和parser的具体过程4. 其他 1. antlr4是用来干什么的? 是用来生成某语言lexer和parser的。 通俗点说,就是输入一个语言的规则描述文件&…...

超级好用的C++实用库之文件目录操作
💡 需要该C实用库源码的大佬们,可扫码关注文章末尾的微信公众号二维码,或搜索微信公众号“希望睿智”。添加关注后,输入消息“超级好用的C实用库”,即可获得源码的下载链接。 概述 文件和目录操作是操作系统层面上的基…...

结合kimi chat的爬虫实战思路
背景 想钻研一下项目组件,找找之后的学习方向。不能自以为是,所以借着网开源项目网站上公布的项目内容看一下,那些是我可以努力去学习的(入门的)。首先需要获取相关内容,于是爬取整理。 任务1:…...

UnsupportedClassVersionError异常如何解决?
下面是异常报错的详细描述 java -version java version "17.0.11" 2024-04-16 LTS Java(TM) SE Runtime Environment (build 17.0.117-LTS-207) Java HotSpot(TM) 64-Bit Server VM (build 17.0.117-LTS-207, mixed mode, sharing) 环境变量已经是jdk17,但…...

LeetCode热题100|动态规划Part.1|70.爬楼梯、118.杨辉三角、198.打家劫舍
70.爬楼梯 代码随想录原题,看这篇文章:C动态规划Part.1|动态规划理论基础、509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯 118.杨辉三角 题目链接:118.杨辉三角 一刷代码 时间复杂度和空间复杂度都造到 O ( n u m R o w s 2 ) O(num…...

python 根据网址和关键词批量下载影像
最近用到了GLASS的LAI产品,但这个产品的文件夹分得很细,我需要的影像又有8个瓦片,一个一个点击很麻烦,于是探索了批量下载的方法 一、下载1幅 import requests import re import os import requests import re# 网页URLurl &…...