当前位置: 首页 > news >正文

MySQL知识点总结(五)——锁

MySQL知识点总结(五)——锁

  • 锁分类
    • 表锁 & 行锁
      • 如何添加表锁?
      • 如何添加行锁?
    • 读锁 & 写锁
    • 行锁 & 间隙锁(gap lock)& 临键锁(next-key lock)
  • 加锁机制分析
    • 可重复读隔离级别下的加锁机制
      • 唯一索引等值查询
      • 非唯一索引等值查询
      • 范围查询
    • 读已提交隔离级别下的加锁机制
  • 如何强行释放锁

锁是每一个关系型数据库都肯定会有的一种处理并发读写冲突的机制。通过加锁,当前事务可以保证它加了锁的行记录,不被别的事务修改,保证了事务的隔离性。

保证事务隔离性的机制,除了加锁以外,还有MVCC,那什么时候加锁,什么时候使用MVCC机制呢?在一个事务中,当我们的查询语句显式的加锁,也就是“select … lock in share mode”或者“select … for update”,以及增删改操作,都会加锁;而普通的“select …”读操作,则通过MVCC来保证基本的隔离性。

在这里插入图片描述

锁分类

首先我们了解一下锁的分类。需要注意的是,基于不同的角度,有不同的锁分类方式。比较常见的锁分类方式有:表锁 & 行锁、读锁 & 写锁、行锁 & 间隙锁(gap lock) & 临键锁(next-key lock)。

表锁 & 行锁

这是基于锁粒度的一种锁分类方式,表锁锁的是整张表,而行锁锁的是一行或者多行记录。表锁的加锁速度较快,但是并发度不高,容易发生锁冲突;而行锁的加锁速度较慢,但是并发度较高,发生锁冲突的概率较小。

在这里插入图片描述

如何添加表锁?

如果是MyISAM存储引擎的话,由于MyISAM是不支持行锁的,一般的增删改SQL,以及我们显式加锁的查询语句,MyISAM都会加表锁,锁住整张表。

如果是InnoDB存储引擎的话,我们想要加表锁,需要通过SQL语句“lock tables … read/write”声明加表锁。

比如我们要对student表加一个写锁,那么SQL语句就是如下这样:

LOCK TABLES student WRITE;

如果我们要对student加一个读锁,那么SQL语句就是如下这样:

LOCK TABLES student READ;

在这里插入图片描述

如何添加行锁?

MyISAM存储引擎是不支持行锁的,所以如果要用MyISAM去加行锁的话,可以洗洗睡了。

InnoDB默认就是加行锁的,如果我们不显式声明加表锁,增删改操作,以及显式声明加锁的select语句都是加行锁的。

读锁 & 写锁

这是另一种锁分类的方式,读写也叫共享锁,读锁和读锁之间并不冲突,也就是说两个读锁可以同时对同一条记录上锁;而写锁与写锁之间是互斥的,一行记录同一时刻只能有一个写锁对其上锁,因此写锁也叫排他锁。

在这里插入图片描述

但是要注意的时,并非读操作就加读锁,写操作就加写锁,当我们提交的是“select … for update”语句时,虽然该语句是一个读操作,但是加的是写锁,也叫排他锁。

行锁 & 间隙锁(gap lock)& 临键锁(next-key lock)

这是InnoDB行锁里的分类:

  • 行锁:只对一行记录加锁。
  • 间隙锁(gap lock):对两条记录中间的间隙加锁,锁住一个区间,但是不包含记录本身。
  • 临键锁(next-key lock):间隙锁 + 行锁,不仅对两条记录间的区间加锁,还会锁住记录本身,前开后闭,也就是锁住后面一条记录,前面的记录不会锁住。

我们通过画图去理解就知道了。

行锁是锁住一行记录:

在这里插入图片描述

间隙锁是锁住一段区间,但是不包含区间前后的记录本身:

在这里插入图片描述

next-key lock的加锁范围是前开后闭的,也就是两条记录间的区间(间隙),再加上该区间的后面一条记录:

在这里插入图片描述

加锁机制分析

接下来分析一下,各种不同情况下InnoDB都是如何加锁的,加的是行锁?间隙锁?还是next-key lock?然后分别对哪些行记录加锁。

在分析之前,我们首先要明白一点,InnoDB的行锁都是加在索引上的,也就是对索引上锁,InnoDB只会对扫描到的索引加锁,没有扫描到的索引是不会加锁的,并且只会对索引中被扫描到的行记录和间隙上锁

可重复读隔离级别下的加锁机制

可重复读隔离级别下,加锁的原则是对被扫描到的索引行记录以及它前面的区间加临键锁next-key lock,但是等值查询时扫描到最后的一条不满足条件的记录则不用上锁,范围查询则连同最后一条扫描到的不满足条件的行记录也给锁上。

除此以外,唯一索引的等值查询,如果命中索引中的某个行记录,则只对该索引行记录加行锁,不再加间隙锁,相当于是临键锁优化成了行锁。

下面一一分析。

唯一索引等值查询

比如我们现在有一张表student,我们查询id等于5的这一条记录:

select * from student where id = 5 for update;

由于是唯一索引,InnoDB当匹配到满足条件的索引行记录时,就不会再扫描,因此在唯一索引等值查询匹配到满足条件的记录时,会对该记录加行锁,不会加间隙锁。

在这里插入图片描述

如果匹配不成功,就会加间隙锁,但是不会加next-key lock,因为是等值查询,扫描到最后的一条不满足条件的记录是不用上锁的。

在这里插入图片描述

非唯一索引等值查询

比如我们的表student中有一列age年龄字段,age字段建立了非唯一索引,现在我们查询age等于30的记录:

select id,age from student age = 30 lock in share mode;

假设student表存在age=30的行记录,并且是这样的排列顺序:

在这里插入图片描述

在age字段的索引中,与age=30的行记录紧挨着的分别是前面的age=20的行记录和后面的age=40的行记录。

那么加锁情况就是这样:

在这里插入图片描述

首先通过age字段的索引,定位到了age=30的行记录,由于不是唯一索引等值查询,因此要加临键锁,那么首先对age=30的字段,连同它前面大于age=20的这一段区间,也就是(20, 30]这一段左开右闭的区间加一个临键锁。然后由于该索引不是唯一索引,因此还要继续往后扫描。

然后扫描到age=40这一行记录,发现不满足条件,由于当前查询是等值查询,不需要对age=40这一行记录上锁,因此对(30,40)这一段左开右开的区间上间隙锁。

由于这里的sql使用的是“lock in share mode”加的读锁,所以只对二级索引加锁,如果使用的时“for update”加的写锁,还会给主键索引上满足条件的行加上行锁。

范围查询

比如我们查询student表中id大于等于5,小于10的记录:

select * from student where id >= 5 and id < 10 for update;

假设student表中的行记录是这样:

在这里插入图片描述

id字段是student表中的主键,在student表的主键索引中,存在id=5的行记录,然后id=5的行记录前面是id=1的行记录,后面是id=10的行记录。

那么加锁情况是这样:

在这里插入图片描述

由于主键id的索引是唯一索引,查找首先匹配到id=5的行记录,会加一个行锁。然后因为查询是范围查询,查找id大于等于5又小于10的记录。于是扫描到id=10的行记录,发现不满足“id < 10”的查询条件,于是不再往后扫描,但是由于不是等值查询,所以会把最后扫描到的id=10的行记录锁上,于是就添加了一个id在(5, 10]区间范围的临键锁。

读已提交隔离级别下的加锁机制

读已提交隔离级别下的加锁规则就相对简单了,读已提交隔离级别下只会加行锁,不会加间隙锁和临键锁。也就是说,无论是等值查询,还是范围查询,都只会对扫描到的行记录加行锁。

比如上面这个范围查询的例子,如果是在读已提交隔离级别下,加锁情况就变成这样:

在这里插入图片描述

如何强行释放锁

如果我们遇到了SQL执行一直被卡住,执行不下去,然后报了等待锁超时的错误,比如下面这种情况:

在这里插入图片描述

此时,如果我们想强行把被持有的锁释放掉,该如何操作呢?

如果是MySQL 5.7 版本,我们可以通过下面这个SQL查询到锁被哪个线程占有:

select * from sys.innodb_lock_waits where locked_table = '`库名`.`表名`' \G;

这个SQL会显示是几号线程占有着锁导致阻塞,然后我们可以使用KILL命令加上对应线程的pid(上面的查询语句会显示线程的pid),强行断开该线程对应的连接,比如占有锁的线程的pid是5,那么我们执行如下命令断开pid为5的线程的连接:

KILL 5;

连接一旦断开,占有的锁就自动被释放。

相关文章:

MySQL知识点总结(五)——锁

MySQL知识点总结&#xff08;五&#xff09;——锁 锁分类表锁 & 行锁如何添加表锁&#xff1f;如何添加行锁&#xff1f; 读锁 & 写锁行锁 & 间隙锁&#xff08;gap lock&#xff09;& 临键锁&#xff08;next-key lock&#xff09; 加锁机制分析可重复读隔离…...

IDEA 2023.2 配置 JavaWeb 工程

目录 1 不使用 Maven 创建 JavaWeb 工程 1.1 新建一个工程 1.2 配置 Tomcat 1.3 配置模块 Web 2 使用 Maven 配置 JavaWeb 工程 2.1 新建一个 Maven 工程 2.2 配置 Tomcat &#x1f4a5;提示&#xff1a;IDEA 只有专业版才能配置 JavaWeb 工程&#xff0c;若是社区版&am…...

软考40-上午题-【数据库】-关系代数运算2-专门的集合运算

一、专门的集合运算 1、投影 示例&#xff1a; 可以用属性名进行投影&#xff0c;也可以用列的序号进行投影。 2、选择 例题 1、笛卡尔积 2、投影 3、选择 3、连接 第一步都要算&#xff1a;笛卡尔积。 3-1、θ连接 示例&#xff1a; 3-2、等值连接 示例&#xff1a; 3-3、自…...

RHEL9安装Python2.7

RHEL9作为2022年5月新推出的版本&#xff0c;较RHEL8有了很多地方的改进&#xff0c;而且自带很多包&#xff0c;功能非常强大&#xff0c;稳定性和流畅度也较先前版本有了很大的提升。RHEL9自带python3.9&#xff0c;但是过高版本的python不可避免地会导致一些旧版本包地不兼容…...

更新至2022年世界各国数字经济发展相关指标(23个指标)

更新至2022年世界各国数字经济发展相关指标&#xff08;23个指标&#xff09; 1、时间&#xff1a;具体指标时间见下文 2、来源&#xff1a;WDI、世界银行、WEF、UNCTAD、SJR、国际电联 3、指标&#xff1a;移动网络覆盖率&#xff08;2000-2022&#xff09;、固定电话普及率…...

vue从flask获取数据并显示

记录一个前后端分离遇到的问题&#xff0c;即vue前端从flask后端获取数据。具体描述如下&#xff1a;flask只负责连接数据库并获取数据库的数据&#xff0c;并返回给前端vue&#xff1b;vue则需要获取后端返回的数据并显示。 方法如下&#xff0c;分别用一个vue组件和一个flas…...

Kafka生产常见问题分析与总结

Kafka生产常见问题分析与总结 消息丢失 生产者 acks 0 不需要等待任何Broker确认收到消息的回复就可以继续发消息 性能最高&#xff0c;但是最容易丢消息&#xff0c;对于数据丢失不敏感的场景可以使用&#xff0c;如大数据统计报表 acks 1 只要等待Broker中的leader成功写…...

重温MySQL

mysql 是什么 mysql 就是一个软件,专门用来管理文件的软件 关系型数据库:采用二维表结构组织和管理数据,并且规定了表和表间数据的关系. 表是由行和列构成,列包含一组命名的属性(也称字段),行包含一条记录.行和列的交集称为数据项 (也称字段值). 如何操作数据库 那就是用sq…...

构造函数,原型,实例,类的关系整理

视频来源js原型链、构造函数和类_哔哩哔哩_bilibili 如视频所说&#xff0c;构造函数的prototype指向原型&#xff0c;实例化的对象的__proto__指向原型&#xff0c;原型通过constructor指向构造函数&#xff0c;正如class里面的constructor方法就相当于Person构造函数一样&am…...

[极客挑战2019]HTTP

这道题考察的是http请求头字段的含义和使用&#xff1b; 具体如下 Referer:来源地址 User-Agent:客户端配置信息&#xff1a;浏览器类型、版本、系统类型等 X-Forwarded-For:代理地址&#xff0c;即数据发出的地址 开始解题&#xff1a;&#xff08;对我这初学者真的烧脑&a…...

发布 rust 源码包 (crates.io)

rust 编程语言的包 (或者 库, library) 叫做 crate, 也就是软件中的一个组件. 一个完整的软件通常由多个 crate 组成, rust 编译器 (rustc) 一次编译一整个 crate, 不同的 crate 可以同时并行编译. rust 官方有一个集中发布开源包的网站 crates.io. 发布在这上面的 crate 可以…...

jQuery 基础、选择器和筛选器

【一】JQuery基础 【1】什么时Jquery &#xff08;1&#xff09;定义 jQuery是一个流行的JavaScript库&#xff0c;旨在简化JavaScript编程和处理HTML文档的任务。它提供了一组易于使用的功能和方法&#xff0c;可以加快开发速度并提高跨浏览器兼容性。一款轻量级的JS框架 …...

网络原理-UDP/TCP协议

协议 在网络通信中,协议是非常重要的一个概念,在下面,我将从不同层次对协议进行分析. 应用层 IT职业者与程序打交道最多的一层,调用系统提供的API写出的代码都是属于应用层的. 应用层中有很多现成的协议,但是更多的,我们需要根据实际情况来进行制作自定义协议. 自定义协议…...

C语言——实用调试技巧——第2篇——(第23篇)

坚持就是胜利 文章目录 一、实例二、如何写出好&#xff08;易于调试&#xff09;的代码1、优秀的代码2、示范&#xff08;1&#xff09;模拟 strcpy 函数方法一&#xff1a;方法二&#xff1a;方法三&#xff1a;有弊端方法四&#xff1a;对方法三进行优化assert 的使用 方法五…...

broom系列包: 整理模型输出结果

broom包 说明 tidy、augment和glance函数的输出总是一个小tibble。 输出从来没有行名。这确保了您可以将它与其他整洁的输出组合在一起&#xff0c;而不用担心丢失信息(因为R中的行名不能包含重复)。 有些列名保持一致&#xff0c;这样它们就可以跨不同的模型进行组合。 tidy(…...

Spring Boot 参数校验机制原理以及如何实现一个自定义校验注解

Spring Boot 参数校验原理 Spring Boot 提供了一种方便的参数校验机制&#xff0c;借助于 JSR-303&#xff08;Bean Validation&#xff09;规范&#xff0c;通过在方法参数上添加校验注解来实现参数校验。下面是 Spring Boot 参数校验的基本原理&#xff1a; JSR-303 标准注解…...

长短期记忆神经网络

目录 LSTM 神经网络架构 分类 LSTM 网络 回归 LSTM 网络 视频分类网络 更深的 LSTM 网络 网络层 分类、预测和预报 序列填充、截断和拆分 按长度对序列排序 填充序列 截断序列 拆分序列 指定填充方向 归一化序列数据 无法放入内存的数据 可视化 LSTM 层架构 …...

解决vscode每次git pull/push都需要输入账号密码

git如何设置用户名 邮箱 密码 //设置用户 git config --global user.name "xxx"//设置邮箱 git config --global user.email "xxxxxx.com"//设置密码 git config --global user.password "xxxxx"解决每次git pull/push操作都需要输入密码 git …...

Rancher实用篇-使用rancher,部署微服务应用

说到rancher&#xff0c;我们必须先了解一下k8s 一、k8s简介 Kubernetes&#xff08;通常简写为 K8s&#xff09;是一个开源的容器管理系统&#xff0c;由Google于2014年发起&#xff0c;并在2015年贡献给Cloud Native Computing Foundation (CNCF)进行维护。它基于Borg项目的…...

爬取m3u8视频

网址&#xff1a;https://www.bhlsm.com/cupfoxplay/609-3-1/ 相关代码&#xff1a; #采集网址&#xff1a;https://www.bhlsm.com/cupfoxplay/609-3-1/ #正常视频网站&#xff1a;完整视频内容 # pip install pycryptodomex #流媒体文件&#xff1a;M3U8&#xff08;把完整的…...

抖音视频抓取软件的优势|视频评论内容提取器|批量视频下载

抖音视频抓取软件在市场上的优势明显&#xff1a; 功能强大&#xff1a;我们的软件支持关键词搜索抓取和分享链接单一视频提取两种方式&#xff0c;满足用户不同的需求。同时&#xff0c;支持批量处理数据&#xff0c;提高用户获取视频的效率。 操作简单&#xff1a;我们的软件…...

apidoc接口文档的自动更新与发布

文章目录 一、概述二、环境准备三、接口文档生成1. 下载源码2. 初始化3.执行 四、文档发布五&#xff0c;配置定时运行六&#xff0c;docker运行 一、概述 最近忙于某开源项目的接口文档整理&#xff0c;采用了apidoc来整理生成接口文档。 apidoc是一个可以将源代码中的注释直…...

Oracle EBS R12.1 FA 批量计划外折旧

在资产工作台上可以进行单个资产的计划外折旧&#xff0c;如果进行批量计划外折旧的话就需要进行开发客户化form或者webadi 进行数据上载后调用FA 标准API了 以下是标准API的demo示例 DECLAREl_trans_rec FA_API_TYPES.trans_rec_type; l_asset_hdr_rec FA_API_TYPES.asset_hdr…...

15.3 基于深度学习的WiFi指纹低成本地点识别

文献来源:Nowicki M, Wietrzykowski J. Low-effort place recognition with WiFi fingerprints using deep learning[C]//Automation 2017: Innovations in Automation, Robotics and Measurement Techniques 1. Springer International Publishing, 2017: 575-584. 摘要 使…...

Git基本操作(1)

Git基本操作&#xff08;1&#xff09; 初始化git本地仓库git本地仓库配置git config user.name 和git config user.emailgit config --unset user.name和git config --unset user.emailgit config --global 认识工作区&#xff0c;暂存区&#xff0c;版本库更深层次理解 git a…...

k8s-helm部署应用 19

Helm部署nfs-client-provisioner&#xff08;存储类&#xff09;&#xff1a; 预先配置好外部的NFS服务器 部署 Helm部署nginx-ingress应用&#xff1a; 添加下载ingress 拉取 解开并修改 部署 测试 回收 helm部署metrics-server&#xff1a; 清除之前的metrics部署 下载…...

OGG-00918 映射中缺少键列 id.

2024-02-23 14:54:49 INFO OGG-02756 从线索文件获取了表 GISTAR.PXPH_PON_ROUTE 的定义。. The following columns did not default because of type mismatches: id OGG-00918 映射中缺少键列 id. 目标端有字段ID&#xff0c;由于mysql自增&#xff0c;所以只能是b…...

QT_day4

1.思维导图 2. 输入闹钟时间格式是小时:分钟 widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);id startTimer(1000);flag1;speecher new QTextT…...

Spring Boot应用集成Actuator组件以后怎么自定义端点暴露信息

一、 前言 在平时业务开发中&#xff0c;我们往往会在spring Boot项目中集成Actuator组件进行系统监控&#xff0c;虽然Actuator组件暴露的端点信息已经足够丰富了&#xff0c;但是特殊场景下&#xff0c;我们也需要自己暴露端点信息&#xff0c;此时应该怎么操作呢&#xff1…...

C# CAD备忘录

Document doc Application.DocumentManager.MdiActiveDocument; Database db doc.Database; Editor ed doc.Editor; 1、获取打开cad文件-文件路径 string fileName db.Filename;//文件名 输出结果 fileName “L:\目录\200401.dwg” 2、获取打开cad文件-文件名称 string fi…...