【MySQL进阶】锁

文章目录

    • 概述
    • 全局锁
      • 语法
      • 特点
    • 表级锁
      • 表锁
      • 意向锁
    • 行级锁
      • 行锁
      • 间隙锁&临键锁
  • 面试
    • 了解数据库的锁吗?
    • 介绍一下间隙锁
    • InnoDB中行级锁是怎么实现的?
    • 数据库在什么情况下会发生死锁?
    • 说说数据库死锁的解决办法

概述

锁机制:数据库为了保证数据的一致性,在共享的资源被并发访问时变得安全有序所设计的一种规则
MySQL中的锁,按照锁的粒度分,分为以下三类:

  • 全局锁:锁定数据库中的所有表。
  • 表级锁:每次操作锁住整张表。
  • 行级锁:每次操作锁住对应的行数据。

全局锁

全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语
句,已经更新操作的事务提交语句都将被阻塞。
其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整
性。

语法

  • 加全局锁
flush tables with read lock ;
  • 释放锁
unlock tables ;	

特点

**特点 **
数据库中加全局锁,是一个比较重的操作,存在以下问题:

  • 如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆。
  • 如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。

在InnoDB引擎中,我们可以在备份时加上参数 --single-transaction 参数来完成不加锁的一致
性数据备份。即在事务执行过程中,可以读取一个一致性的数据库快照。在备份过程中,通过使用快照读取,可以读取备份时一致性的数据,而不受其他并发事务的影响。

mysqldump --single-transaction -uroot –p123456 itcast > itcast.sql 


表级锁

表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、
InnoDB、BDB等存储引擎中。注意MyISAM只支持表级锁。
对于表级锁,主要分为以下三类:

  • 表锁
  • 元数据锁(meta data lock,MDL)
  • 意向锁

表锁

对于表锁,分为两类:

  • 表共享读锁(read lock) :对指定表加了读锁,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求。
  • 表独占写锁(write lock):对指定表加了写锁,会阻塞其他用户对同一表的读和写操作。

加锁命令:读锁:所有连接只能读取数据,不能修改。 写锁:其他连接不能查询和修改数据

-- 读锁
LOCK TABLE table_name READ;

-- 写锁
LOCK TABLE table_name WRITE;
  • 解锁命令:客户断开连接也会解锁
-- 将当前会话所有的表进行解锁
UNLOCK TABLES;

### **元数据锁** meta data lock , 元数据锁,简写MDL
MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维
护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。**为了避免DML与 **
**DDL冲突,保证读写的正确性。 **
这里的元数据,大家可以简单理解为就是一张表的表结构。 也就是说,某一张表涉及到未提交的事务
时,是不能够修改这张表的表结构的。
在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变
更操作的时候,加MDL写锁(排他)。
常见的SQL操作时,所添加的元数据锁:
lock tables xxx read / writeSHARED_READ_ONLY / SHARED_NO_READ_WRITE
select 、
select … lock in share mode


SHARED_READ
与SHARED_READ、
SHARED_WRITE兼容,与 EXCLUSIVE互斥
insert 、update、 delete、select … for update

SHARED_WRITE
与SHARED_READ、
SHARED_WRITE兼容,与EXCLUSIVE互斥
alter table …EXCLUSIVE与其他的MDL都互斥

意向锁

为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行
数据是否加锁,使用意向锁来减少表锁的检查。

假如没有意向锁,客户端一对表加了行锁后,客户端二如何给表加表锁呢。

  1. 首先客户端一,开启一个事务,然后执行DML操作,在执行DML语句时,会对涉及到的行加行锁。
  2. 当客户端二,想对这张表加表锁时,会检查当前表是否有对应的行锁,如果没有,则添加表锁,此时就会从第一行数据,检查到最后一行数据,效率较低

有了意向锁之后 :

  1. 客户端一,在执行DML操作时,会对涉及的行加行锁,同时也会对该表加上意向锁。
  2. 而其他客户端,在对这张表加表锁的时候,会根据该表上所加的意向锁来判定是否可以成功加表锁,而不用逐行判断行锁情况了

分类

  • 意向共享锁(IS): 由语句select … lock in share mode添加 。 与 表锁共享锁 (read)兼容,与表锁排他锁(write)互斥。
  • 意向排他锁(IX): 由insert、update、delete、select…for update添加 。与表锁共享锁(read)及排他锁(write)都互斥,意向锁之间不会互斥。

兼容性如下所示: S、X分别是行级共享锁和行级排他锁
一旦事务提交了,意向共享锁、意向排他锁,都会自动释放。

可以通过以下SQL,查看意向锁及行锁的加锁情况:

select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from
performance_schema.data_locks;

行级锁

行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在
InnoDB存储引擎中。
InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的
锁。对于行级锁,主要分为以下三类:

  • 行锁(Record Lock):锁定单个行记录的锁,防止其他事务对此行进行update和delete。在

RC、RR隔离级别下都支持
image.png

  • 间隙锁(Gap Lock):锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事

务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持。
image.png
临键锁(Next-Key Lock):行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。
在RR隔离级别下支持、image.png

行锁

**介绍 **
InnoDB实现了以下两种类型的行锁:
共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。
排他锁(X):允许获取到排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。

两种行锁的兼容情况如下:
image.png

常见的SQL语句,在执行时,所加的行锁如下:

SQL行锁类型
INSERT、UPDATE、DELETE排他锁
SELECT…不加锁
SELECT … LOCK IN SHARE MODE共享锁
SELECT … FOR UPDATE排它锁

特点
默认情况下,InnoDB在 REPEATABLE READ事务隔离级别运行,InnoDB使用 next-key 锁进行搜
索和索引扫描,以防止幻读。

  • 针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。
  • InnoDB的行锁是针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁。

间隙锁&临键锁

InnoDB 会对间隙(GAP)进行加锁,就是间隙锁 (RR 隔离级别下才有该锁)。间隙锁之间不存在冲突关系,多个事务可以同时对一个间隙加锁,但是间隙锁会阻止往这个间隙中插入一个记录的操作
InnoDB 加锁的基本单位是 next-key lock(临键锁),该锁是行锁和 gap lock 的组合(X or S 锁),但是加锁过程是分为间隙锁和行锁两段执行

  • 临键锁可以保护当前记录和前面的间隙,遵循左开右闭原则,单纯的间隙锁是左开右开
  • 假设有 10、11、13,那么可能的临键锁包括:(负无穷,10]、(10,11]、(11,13]、(13,正无穷)

几种索引的加锁情况:

  • 索引上的等值查询(唯一索引),给不存在的记录加锁时, 优化为间隙锁 。
  • 索引上的等值查询(非唯一普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁。
  • 索引上的范围查询(唯一索引)–会访问到不满足条件的第一个值为止。

间隙锁优点:RR 级别下间隙锁可以解决事务的一部分的幻读问题,通过对间隙加锁,可以防止读取过程中数据条目发生变化。一部分的意思是不会对全部间隙加锁,只能加锁一部分的间隙
间隙锁危害:

  • 当锁定一个范围的键值后,即使某些不存在的键值也会被无辜的锁定,造成在锁定的时候无法插入锁定键值范围内的任何数据,在某些场景下这可能会对性能造成很大的危害,影响并发度
  • 事务 A B 同时锁住一个间隙后,A 往当前间隙插入数据时会被 B 的间隙锁阻塞,B 也执行插入间隙数据的操作时就会产生死锁

当涉及到索引上的不同类型的查询时,以下是一些具体的例子,展示了在不同情况下锁住的范围:

举例说明

  1. 索引上的等值查询(唯一索引):

    假设有一个表users,有一个唯一索引id,用于存储用户的ID。通过以下查询示例加锁:

   SELECT * FROM users WHERE id = 100 FOR UPDATE;

如果ID为100的记录存在,InnoDB会使用行级锁来锁定该行记录。如果ID为100的记录不存在,此时InnoDB会优化为间隙锁。对于该示例,间隙锁会锁住在ID为99和ID为101之间的间隙,以防止其他事务在该范围内插入数据。

  1. 索引上的等值查询(非唯一普通索引):

    假设有一个表orders,有一个普通索引customer_id,用于存储订单的顾客ID。通过以下查询示例加锁:

 SELECT * FROM orders WHERE customer_id = 200 FOR UPDATE;

如果有多个订单关联到顾客ID为200,InnoDB会使用行级锁来锁定这些相关订单的行记录。这里的锁的范围是所有满足查询条件的行记录。

  1. 索引上的范围查询(唯一索引):

    假设有一个表products,有一个唯一索引product_id,用于存储产品的ID。通过以下查询示例加锁:

   SELECT * FROM products WHERE product_id BETWEEN 100 AND 200 FOR UPDATE

InnoDB会遍历并锁定在ID为100到ID为200的记录范围内的行记录。这个范围包括ID为100和ID为200的行记录。对于这个示例,锁的范围是一个范围区间。

面试

了解数据库的锁吗?

锁是数据库系统区别于文件系统的一个关键特性,锁机制用于管理对共享资源的并发访问。下面我们以
MySQL数据库的InnoDB引擎为例,来说明锁的一些特点。
锁的类型:
InnoDB存储引擎实现了如下两种标准的行级锁:

  • 共享锁(S Lock),允许事务读一行数据。
  • 排他锁(X Lock),允许事务删除或更新一行数据。

如果一个事务T1已经获得了行r的共享锁,那么另外的事务T2可以立即获得行r的共享锁,因为读取并没有改变行r的数据,称这种情况为锁兼容。但若有其他的事务T3想获得行r的排他锁,则其必须等待事务 T1、T2释放行r上的共享锁,这种情况称为锁不兼容。下图显示了共享锁和排他锁的兼容性,可以发现X 锁与任何的锁都不兼容,而S锁仅和S锁兼容。需要特别注意的是,S和X锁都是行锁,兼容是指对同一记录(row)锁的兼容性情况。
image.png
锁的粒度:
InnoDB存储引擎支持多粒度锁定,这种锁定允许事务在行级上的锁和表级上的锁同时存在。为了支持 在不同粒度上进行加锁操作,InnoDB存储引擎支持一种额外的锁方式,称之为意向锁。意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度上进行加锁。
InnoDB存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁。设计目的主要是为了在一个事 务中揭示下一行将被请求的锁类型。其支持两种意向锁:

  • 意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁。
  • 意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁。

由于InnoDB存储引擎支持的是行级别的锁,因此意向锁其实不会阻塞除全表扫以外的任何请求。故表 级意向锁与行级锁的兼容性如下图所示。
image.png

锁的算法:
InnoDB存储引擎有3种行锁的算法,其分别是: Record Lock:单个行记录上的锁。
Gap Lock:间隙锁,锁定一个范围,但不包含记录本身。
Next-Key Lock∶Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身。

Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这时InnoDB存储引擎会使用隐式的主键来进行锁定。Next-Key Lock是结合了Gap Lock和Record Lock的一种锁定算法,在Next-Key Lock算法下,InnoDB对于行的查询都是采用这种锁定算法。采用Next-Key Lock的锁定技术称为Next-Key Locking,其设计的目的是为了解决Phantom Problem(幻 读)。而利用这种锁定技术,锁定的不是单个值,而是一个范围,是谓词锁(predict lock)的一种改进。
关于死锁:
死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。若无外力 作用,事务都将无法推进下去。
解决死锁问题最简单的一种方法是超时,即当两个事务互相等待时,当一个等待时间超过设置的某一阈 值时,其中一个事务进行回滚,另一个等待的事务就能继续进行。
除了超时机制,当前数据库还都普遍采用wait-for graph(等待图)的方式来进行死锁检测。较之超时的解决方案,这是一种更为主动的死锁检测方式。InnoDB存储引擎也采用的这种方式。wait-for graph 要求数据库保存以下两种信息:
锁的信息链表; 事务等待链表;
通过上述链表可以构造出一张图,而在这个图中若存在回路,就代表存在死锁,因此资源间相互发生等 待。这是一种较为主动的死锁检测机制,在每个事务请求锁并发生等待时都会判断是否存在回路,若存 在则有死锁,通常来说InnoDB存储引擎选择回滚undo量最小的事务。
锁的升级:
锁升级(Lock Escalation)是指将当前锁的粒度降低。举例来说,数据库可以把一个表的1000个行锁升级为一个页锁,或者将页锁升级为表锁。
InnoDB存储引擎不存在锁升级的问题。因为其不是根据每个记录来产生行锁的,相反,其根据每个事 务访问的每个页对锁进行管理的,采用的是位图的方式。因此不管一个事务锁住页中一个记录还是多个 记录,其开销通常都是一致的。

介绍一下间隙锁

InnoDB存储引擎有3种行锁的算法,间隙锁(Gap Lock)是其中之一。间隙锁用于锁定一个范围,但不包含记录本身。它的作用是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产 生。

InnoDB中行级锁是怎么实现的?

InnoDB行级锁是通过给索引上的索引项加锁来实现的。只有通过索引条件检索数据,InnoDB才使用行 级锁,否则,InnoDB将使用表锁。
当表中锁定其中的某几行时,不同的事务可以使用不同的索引锁定不同的行。另外,不论使用主键索 引、唯一索引还是普通索引,InnoDB都会使用行锁来对数据加锁。

数据库在什么情况下会发生死锁?

死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。若无外力 作用,事务都将无法推进下去。下图演示了死锁的一种经典的情况,即A等待B、B等待A,这种死锁问 题被称为AB-BA死锁。
image.png

说说数据库死锁的解决办法

解决死锁问题最简单的一种方法是超时,即当两个事务互相等待时,当一个等待时间超过设置的某一阈值时,其中一个事务进行回滚,另一个等待的事务就能继续进行。
除了超时机制,当前数据库还都普遍采用wait-for graph(等待图)的方式来进行死锁检测。较之超时的解决方案,这是一种更为主动的死锁检测方式。InnoDB存储引擎也采用的这种方式。wait-for graph 要求数据库保存以下两种信息:

  • 锁的信息链表;
  • 事务等待链表;

通过上述链表可以构造出一张图,而在这个图中若存在回路,就代表存在死锁,因此资源间相互发生等 待。这是一种较为主动的死锁检测机制,在每个事务请求锁并发生等待时都会判断是否存在回路,若存在则有死锁,通常来说InnoDB存储引擎选择回滚undo量最小的事务。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++进阶--哈希的应用之位图和布隆过滤器

哈希的应用之位图和布隆过滤器 一、位图1.1 位图(bitset)的提出1.2 位图的概念1.3 位图的模拟实现1.3.1 位图的底层结构1.3.2 位图的成员函数1.3.2.1 位图的构造1.3.2.2 位图的插入:set1.3.2.3 位图的删除:reset1.3.2.4 位图的查找…

LLM for Kernel Fuzzing

KernelGPT: Enhanced Kernel Fuzzing via Large Language Models 1.Introduction2.Background2.1.Kernel and Device Drivers2.2.Kernel Fuzzing2.2.1.Syzkaller规约2.2.2.规约生成 3.Approach3.1.Driver Detection3.2.Specification Generation3.2.1.Command Value3.2.2.Argum…

鸿蒙自定义刷新组件使用

前言 DevEco Studio版本:4.0.0.600 1、RefreshLibrary_HarmonyOS.har,用于HarmonyOS "minAPIVersion": 9, "targetAPIVersion": 9, "apiReleaseType": "Release", "compileSdkVersion": "3.…

【Redis】Redis如何实现key的过期删除

​ 🍎个人博客:个人主页 🏆个人专栏:Redis ⛳️ 功不唐捐,玉汝于成 ​ 目录 前言 正文 结语 我的其他博客 前言 在当今信息时代,数据的快速存储和高效检索成为了软件系统设计中的核心需求。Redis作为…

idea中git提交代码更改作者名字

代码提交远程的时候显示的是上一个离职同事的用户名,有两种方法进行更改 在C盘【C:\Users\Administrator】中找到.gitconfig文件 进行更改 打开文件 将姓名以及邮箱改成自己的即可 [user] name xxxxx email xxxxx163.com 如图所示 命令行更改 在Termi…

ESP32-WROVER-DEV连接W5500实现有线网络

目的:ESP32-WROVER-DEV相机模块连接W5500模块,实现有线网络的连接。 开发环境:Arduino 2.1.1 可以实现的功能:可以使用web的ping访问,ESP32的LED IO2闪烁。 硬件连接如下图: 模块硬件的导线连接 W5500 …

SpringBoot项目整合MybatisPlus并使用SQLite作为数据库

文章目录 SQLite介绍搭建项目创建项目修改pom.xml SQLite查看SQLite是否安装创建数据库创建数据表IDEA连接SQLitenavicat连接SQLite数据库 后端增删改查接口实现MybatisX生成代码不会生成看这个UserUserMapperUserMapper.xml controller创建配置文件application.yaml启动类Incr…

行测-判断:2.类比推理

行测-判断:2.类比推理 给出一组相关的词,要求通过观察分析,在备选答案中找出一组与之在逻辑关系上最为贴近或相似的词。 1. 语义关系★★ 1.1 近义关系,反义关系 C,反义词 B,BD 都是近义词,考…

JavaEE-SSM-订单管理-后端增删改查(二)

.2.5 添加 编写OrderMapper接口中的insert方法 编写OrderService接口中的save方法 编写OrderServiceImpl实现类中的save方法 编写OrderController中的add方法 编写OrderMapper接口中的insert方法 /*** 插入* param order* return*/Insert("insert into order(oid,pr…

MySQL之数据库DDL

文章目录 MySQL数据库基本操作数据定义DDL对数据库的常用操作创建表修改表格式结构 MySQL数据库基本操作 首先我们先了解SQL的语言组成,他分为四个部分 数据定义语言(DDL)数据操纵语言(DML)数据控制语言(…

如何使用宝塔面板搭建Typecho博客站点并结合内网穿透远程访问

文章目录 前言1. 安装环境2. 下载Typecho3. 创建站点4. 访问Typecho5. 安装cpolar6. 远程访问Typecho7. 固定远程访问地址8. 配置typecho 前言 Typecho是由type和echo两个词合成的,来自于开发团队的头脑风暴。Typecho基于PHP5开发,支持多种数据库&#…

算法(4)——前缀和

目录 一、前缀和的定义 二、一维前缀和 三、一维前缀和OJ题 3.1、前缀和 3.2、寻找数组中心下标 3.3、除自身以外数组的乘积 3.4、和为K的数组 3.5、和可被K整除的子数组 3.6、连续数组 四、二位前缀和 4.1、二维前缀和 4.2、矩阵区域和 一、前缀和的定义 对于一个…

Quartz框架中的Corn表达式

Cron 表达式是一个字符串,分为 6 或 7 个域,每一个域代表一个含义 Cron 有如下两种语法格式: (1)Seconds Minutes Hours Day Month Week Year (2)Seconds Minutes Hours Day Month Week 一、…

Java SE:面向对象(下)

1. static关键字 静态区的特点:静态区里面的每一样东西都是唯一有且仅有一个的,如此时str1 "abc"即此时静态区里面已经创建了字符串abc并将abc地址赋给str1,后面在进行赋值也不会在静态区开辟一串新的"abc" 1.1 static修…

蓝桥杯省赛无忧 课件38 第4次学长带练配套课件

01 最大数组和 02 四元组问题 03 鸡哥的购物挑战 04 冒险者公会 05 明日方舟大挑战 06 七段码

一.Winform使用Webview2(Edge浏览器核心) 创建demo(Demo1)实现回车导航到指定地址

Winform使用Webview2创建demo1实现回车导航到指定地址 往期目录参考文档实现1.安装visual studio2.创建单窗口应用3.修改项目中的窗体名称MainForm4.添加按钮5.添加窗口Demo16.在Demo1中添加WebView2 SDK7.在Demo1窗体中选择添加textbox和webview28.在MainForm.cs窗体中添加but…

idea——git提交到本地记录如何退回/删除

目录 一、git提交到本地记录如何退回/删除 一、git提交到本地记录如何退回/删除 git提交到本地记录,如下图【更新】记录,表示本次提交到git本地需要退回/删除的操作: 选中项目,右键点击【git】——>【Show History】——>…

vscode运行python,终端能正常运行,输出(Code Runner)不能正常运行

右键->Run Code报错: [Done] exited with code9009 in 0.111 seconds 我的解决方案:仔细检查自己选的python.exe(解释器)在path环境变量中是否存在或路径是否正确!!! 我就是太自信了&#xf…

REVIT二次开发 自动门窗墙体标注

步骤1 步骤2 步骤3 using System; using System.Collections.Generic; using System.Linq; using System

爬虫安居客新房

一、首先看网址 后面有全部代码 https://hf.fang.anjuke.com/loupan/baohequ/p3 这种形式很好分析,https://hf.fang.anjuke.com/loupan/行政区域页码 xinfang_area ["feixixian", "baohequ", "shushanqu", "luyangqu",…