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.hqwc.cn/news/491401.html

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

相关文章

OpenAI视频生成Sora技术简析

基本介绍 Sora是春节期间OpenAI发布的产品&#xff0c;主要是通过文字描述生成视频&#xff0c;通过大规模视频数据训练而成的生成模型&#xff0c;当前还没开放试用。官方发布的技术报告&#xff1a;https://openai.com/research/video-generation-models-as-world-simulators…

趣学贝叶斯定理:贝叶斯定理的先验概率、似然和后验概率(1)

在第7章中&#xff0c;我们讨论了如何利用空间推理去推导贝叶斯定理。现在研究如何将贝叶斯定理当作一种概率工具&#xff0c;对不确定性进行逻辑推理。本章将利用贝叶斯定理来计算和量化在给定数据的情况下&#xff0c;信念有多大的可能性为真。为此&#xff0c;需要使用该定理…

019 Spring Boot+Vue 电影院会员管理系统(源代码+数据库+文档)

部分代码地址&#xff1a; https://github.com/XinChennn/xc019-cinema 一、系统介绍 cinema项目是一套电影院会员管理系统&#xff0c;使用前后端分离架构开发包含管理员、会员管理、会员卡管理、电影票、消费记录、数据统计等模块 二、所用技术 后端技术栈&#xff1a; …

【泰山派RK3566】智能语音助手(一)移植Kaldi语音转文字

文章目录 移植过程硬件资源下载测试 移植过程 参考我的这篇博客 【RV1126】移植kaldi实时语音识别 硬件 资源下载 链接&#xff1a;https://pan.baidu.com/s/1x1udT5eNzzQHoPOTCQ182A?pwdlief 提取码&#xff1a;lief –来自百度网盘超级会员V6的分享 下载的文件里面有一个…

全志H713/H618方案:调焦电机(相励磁法步进电机)的驱动原理、适配方法

一、篇头 全志H713平台&#xff0c;作为FHD投影的低成本入门方案&#xff0c;其公板上也配齐了许多投影使用的模组&#xff0c;本文即介绍投影仪调焦所用的步进电机&#xff0c;此模组的驱动原理、配制方法、调试方法。因为条件限制&#xff0c;本文采用的是H618香橙派Z3平台&…

Escalate_Linux(4)-利用SUDO实现提权

利用SUDO实现提权 利用用户的sudo授权获得root的shell cat /etc/passwd cat /etc/sudoers 命令没有权限 echo "cat /etc/sudoers" >/tmp/ls chmod 755 /tmp/ls export PATH/tmp:$PATH /home/user5/script 想办法更改user1的口令 echo echo "user1:xiao…

sql-labs第46关(order by盲注脚本)

一、环境 网上有自己找 二、解释 order by 注入我们看他的true和false来进行注入出来 二、实操 让我们用sort 看看源码 最终我们的id是放到order by后面了 如果我们直接用列去排序 ?sortusername/password username&#xff1a; password&#xff1a; 可以看到顺序是不…

每日五道java面试题之spring篇(六)

目录&#xff1a; 第一题 ApplicationContext通常的实现是什么&#xff1f;第二题 什么是Spring的依赖注入&#xff1f;第三题 依赖注入的基本原则第四题 依赖注入有什么优势&#xff1f;第五题 有哪些不同类型的依赖注入实现方式&#xff1f; 第一题 ApplicationContext通常的…

Python及Pycharm专业版下载安装教程(Python 3.11版)附JetBrains学生认证教程

目录 一、Python下载及安装1、Python下载2、Python安装3、验证是否安装成功 二、PyCharm下载及安装1、PyCharm下载2、PyCharm安装3、激活PyCharm 三、JetBrains学生认证 本篇主要介绍Python和PyCharm专业版的下载及安装方式&#xff0c;以及通过两种方式进行JetBrains学生认证。…

HUAWEI Programming Contest 2024(AtCoder Beginner Contest 342)

D - Square Pair 题目大意 给一长为的数组&#xff0c;问有多少对&#xff0c;两者相乘为非负整数完全平方数 解题思路 一个数除以其能整除的最大的完全平方数&#xff0c;看前面有多少个与其余数相同的数&#xff0c;两者乘积满足条件&#xff08;已经是完全平方数的部分无…

DALL-E 系列 (1-3)

DALL-E 系列 (1-3) 本文主要梳理 DALL-E 系列图像生成模型的整体框架&#xff0c;相关论文中都包含了丰富的训练、优化细节&#xff0c;对这些细节本文不做过多介绍&#xff0c;有兴趣的读者可以阅读原文。注意&#xff0c;在阅读本文之前&#xff0c;最好先了解 VAE、VQVAE、…

解决启动服务报./nginx -s reload nginx: [emerg] unknown directive “错误

重启服务报错 bug: ./nginx -s reload nginx: [emerg] unknown directive "? 原因&#xff1a; 一、可能打开没有关闭 二、刚刚编辑的没成功&#xff0c;乱码了&#xff0c;格式问题&#xff0c;重新配置