超全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下载(精力所致,必有精品) …...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
