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;

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

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

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

相关文章

MATLAB:数组与矩阵

2.1 数组运算 数组运算时MATLAB计算的基础。由于MATLAB面向对象的特性&#xff0c;这种数值数组称为MATLAN最重要的一种内建数据类型&#xff0c;而数组运算就是定义这种数据结果的方法。 2.1.1 数组的创建和操作 在MATLAB中一般使用方括号“[]”、逗号“,”、空格和分号“;…

数据结构与算法相关题解20240225

数据结构与算法相关题解20240225 一、58. 最后一个单词的长度二、48. 旋转图像三、69. x 的平方根四、50. Pow(x, n) 一、58. 最后一个单词的长度 简单 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度…

445. 两数相加 II(Java)

目录 题目描述&#xff1a;输入&#xff1a;输出&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外&am…

CSP-202209-3-防疫大数据

CSP-202209-3-防疫大数据 解题思路 一、数据结构定义 对于大模拟的题&#xff0c;合适的数据结构选择十分重要&#xff0c;正确的数据结构选择能够有效的提升解题效率 // 漫游消息结构体 struct RoamingData {int date, user, region; };vector<RoamingData> roamin…

汇编反外挂

在软件保护领域&#xff0c;尤其是游戏保护中&#xff0c;反外挂是一个重要的议题。外挂通常指的是一种第三方软件&#xff0c;它可以修改游戏数据、操作游戏内存或提供其他作弊功能&#xff0c;从而给玩家带来不公平的优势。为了打击外挂&#xff0c;游戏开发者会采取一系列措…

web安全学习笔记【16】——信息打点(6)

信息打点-语言框架&开发组件&FastJson&Shiro&Log4j&SpringBoot等[1] #知识点&#xff1a; 1、业务资产-应用类型分类 2、Web单域名获取-接口查询 3、Web子域名获取-解析枚举 4、Web架构资产-平台指纹识别 ------------------------------------ 1、开源-C…

代码随想录算法训练营第二十四天补|● 回溯理论基础 ● 77. 组合

回溯理论基础、组合问题 回溯理论基础 回溯能解决的问题 回溯的本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出我们想要的答案 回溯如何穷举&#xff1a; 横向遍历for循环&#xff0c;纵向遍历backtracking&#xff08;递归&#xff09;&#xff0c;一般来说&#…

pikachu靶场-RCE

介绍&#xff1a; RCE(remote command/code execute)概述 RCE漏洞&#xff0c;可以让攻击者直接向后台服务器远程注入操作系统命令或者代码&#xff0c;从而控制后台系统。 远程系统命令执行 一般出现这种漏洞&#xff0c;是因为应用系统从设计上需要给用户提供指定的远程命…

【数据结构】排序

目录 1.排序的概念及其应用 1.1排序的概念 1.2排序的应用 1.3常见的排序算法 2.常见排序算法的实现 2.1插入排序的实现 2.11基本思想 2.12直接插入排序 2.2希尔排序&#xff08;缩小增量排序&#xff09; 2.21基本思想 2.22希尔排序 2.3选择排序 2.31基本思想 2.3…

蓝桥杯《数字三角形》

题目描述 上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径&#xff0c;把路径上面的数加起来可以得到一个和&#xff0c;你的任务就是找到最大的和。 路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右边的那个数。此外&…

JavaScript 进阶02

深入对象 构造函数 构造函数是用于创建对象的函数。 <script> //构造函数 构造函数的首字母大写 function Obj(name,age,aaa){this.namenamethis.ageage } //调用函数 const obj1new Obj("小明",4) console.log(obj1) </script> 使用 new 关键字调用…

Java之线程同步、synchronized用法及原理

线程的同步 场景1&#xff1a;两个线程同时访问一个变量&#xff0c;一个线程自增&#xff0c;一个线程自减 public class thread11 {public static void main(String[] args) throws InterruptedException {Thread thread1 new AddThread();Thread thread2 new DecThread(…

如何开发通过蓝牙技术实现灯光智能调节的小程序

近年来&#xff0c;随着智能家居市场日渐兴起&#xff0c;人们对于家居生活品质的需求不断提升。在这一背景下&#xff0c;蓝牙智能调节小程序的开发能够为客户提供更便捷、智能化的LED灯光调节方案。需求方想要实现通过蓝牙开发实现LED灯光亮度和颜色的智能调节&#xff0c;同…

DAY29--learning English

一、积累 1.sign up for 2.business trip 3.calendar 4.acne 5.band-aid 6.scar 7.prescription 8.pimple 9.saucy 10.slurp 11.germaphobe 12.shred 13.boggle 14.platser 15.lick 16.sling 17.smack 18.stereotype 19.salmon 20.cable 二、练习 1.牛津原译 calendar. /ˈk…

Windows中的Git Bash运行conda命令:未找到命令的错误(已解决)

在windows中的Gitbash中 打开激活conda环境&#xff0c;并运行&#xff08;前提是你先安装好git&#xff08;自己去官网下载&#xff09;&#xff09;。 要能够在Gitbash上运行Conda&#xff0c; 临时配置 如果你只是临时用一下&#xff0c;就是临时爽一把&#xff0c;那就按…

线程池(ThreadPoolExecutor,as_completed)和scrapy框架初步构建——学习笔记

用法1&#xff1a;map函数 with ThreadPoolExecutor() as pool: results pool.map(craw,utls)for result in results:print(result) 1.Scrapy框架&#xff1a; 五大结构&#xff1a;引擎&#xff0c;下载器&#xff0c;爬虫&#xff0c;调度器&#xff0c;管道&#x…

【vue】provide/inject

provide/ inject这对选项需要一起使用&#xff0c;以允许一个祖先组件向其所有子孙后代注入一个依赖&#xff0c;不论组件层次有多深&#xff0c;并在起上下游关系成立的时间里始终生效。 通途点来讲可以用来实现隔代传值&#xff0c;传统的props只能父传子&#xff0c;而 prov…

1.QT简介(介绍、安装,项目创建等)

1. QT介绍 Qt&#xff08;官方发音 [kju:t]&#xff09;是一个跨平台的C开发库&#xff0c;主要用来开发图形用户界面&#xff08;Graphical User Interface&#xff0c;GUI&#xff09;程序 Qt 是纯 C 开发的&#xff0c;正常情况下需要先学习C语言、然后在学习C然后才能使用…

Linux--shell编程中内部表和外部表之间的转换

内部表和外部表之间的转换 1、查询表的类型 desc formatted student; Table Type: MANAGED_TABLE 2、修改内部表student为外部表 alter table student set tblproperties(EXTERNALTRUE); 3、查询表的类型 desc formatted student; Table Type: EXT…

神经网络系列---归一化

文章目录 归一化批量归一化预测阶段 测试阶段γ和β&#xff08;注意&#xff09;举例 层归一化前向传播反向传播 归一化 批量归一化 &#xff08;Batch Normalization&#xff09;在训练过程中的数学公式可以概括如下&#xff1a; 给定一个小批量数据 B { x 1 , x 2 , … …