我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Mysql七种锁

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Mysql七种锁

MySQL是目前世界上最流行的数据库,InnoDB是MySQL最流行的存储引擎,它在大数据量高并发量的业务场景下,有着非常良好的性能表现,之所以如此,是和InnoDB的锁机制相关。

总的来说,InnoDB共有七种类型的锁:

(1)自增锁(Auto-inc Locks);

(2)共享/排它锁(Shared and Exclusive Locks);

(3)意向锁(Intention Locks);

(4)插入意向锁(Insert Intention Locks);

(5)记录锁(Record Locks);

(6)间隙锁(Gap Locks);

(7)临键锁(Next-key Locks);

第一种,自增锁(Auto-inc Locks)

【案例说明】

MySQL,InnoDB,默认的隔离级别(RR),假设有数据表:

t(id AUTO_INCREMENT, name);

数据表中有数据:

1, wangwu

2, zhangsan

3, lisi

事务A先执行,还未提交:

insert into t(name) values(xxx);

事务B后执行:

insert into t(name) values(ooo);

问:事务B会不会被阻塞?

【案例分析】

InnoDB在RR隔离级别下,尝试解决幻读问题,上面这个案例中:

(1)事务A先执行insert,会得到一条(4, xxx)的记录,由于是自增列,故不用显示指定id为4,InnoDB会自动增长,注意此时事务并未提交;

(2)事务B后执行insert,假设不会被阻塞,那会得到一条(5, ooo)的记录;

此时,并未有什么不妥,但如果,

(3)事务A继续insert:

insert into t(name) values(xxoo);

会得到一条(6, xxoo)的记录。

(4)事务A再select:

select * from t where id>3;

得到的结果是:

4, xxx

6, xxoo

画外音:不可能查询到5的记录,在RR的隔离级别下,不可能读取到还未提交事务生成的数据。

这对于事务A来说,就很奇怪了,AUTO_INCREMENT的列,连续插入了两条记录,一条是4,接下来一条变成了6,就像莫名其妙的幻影。

【自增锁】

自增锁是一种特殊的表级别锁(table-level lock),专门针对事务插入AUTO_INCREMENT类型的列。

最简单的情况,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。

与此同时,InnoDB提供了innodb_autoinc_lock_mode配置,可以调节与改变该锁的模式与行为。

第二种,共享/排它锁(Shared and Exclusive Locks)

(1)事务拿到某一行记录的共享S锁,才可以读取这一行;

(2)事务拿到某一行记录的排它X锁,才可以修改或者删除这一行;

其兼容互斥表如下:

即:

(1)多个事务可以拿到一把S锁,读读可以并行;

(2)而只有一个事务可以拿到X锁,写写/读写必须互斥;

共享/排它锁的潜在问题是,不能充分的并行,解决思路是数据多版本

第三种,意向锁(Intention Locks)

InnoDB支持多粒度锁(multiple granularity locking),它允许行级锁与表级锁共存,实际应用中,InnoDB使用的是意向锁。

意向锁是指,未来的某个时刻,事务可能要加共享/排它锁了,先提前声明一个意向。

意向排它锁(intention exclusive lock, IX),它预示着,事务有意向对表中的某些行加排它X锁

select * from demo where id = 1 for update

上述语句执行的时候会对demo这张表添加一个表级别的意向排它锁,并且在id=1的记录上加一个行级别排它锁。

意向共享锁(intention shared lock, IS),它预示着,事务有意向对表中的某些行加共享S锁

select * from demo where id = 1

上述语句执行的时候会对demo这张表添加一个表级别的意向共享锁,并且在id=1的记录上加一个行级别共享锁。

第四种,插入意向锁(Insert Intention Locks)

对已有数据行的修改与删除,必须加强互斥锁X锁,那对于数据的插入,是否还需要加这么强的锁,来实施互斥呢?插入意向锁,孕育而生。

插入意向锁,是间隙锁(Gap Locks)的一种(所以,也是实施在索引上的),它是专门针对insert操作的。

1、插入意向锁是Gap锁,不是意向锁,是insert操作产生的。当多个事务同时将不同的数据写入同一个索引间隙时,不需要等待其他事务完成,也不会发生锁等待。

假定有一个记录索引包含键值4和7,不同的事务分别插入5和6,每个事务都会产生一个插入意向锁,加到4-7之间,得到插入行上的排他锁,但不会相互锁定,因为数据行并不冲突。

2. 插入意向锁不会阻止任何锁,插入记录会持有记录锁。

insert into test_user(user_id,name,age) values(2,'b',10)------- TRX HAS BEEN WAITING 18 SEC FOR THIS LOCK TO BE GRANTED:RECORD LOCKS space id 6628 page no 4 n bits 72 index `index_user` of table `test`.`test_user` trx id 117851203插入意向锁 lock_mode X insert intention waitingRecord lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0 0: len 8; hex 73757072656d756d; asc supremum;;

以上就是mysql插入意向锁的使用

第五种,记录锁(Record Locks)

记录锁,它封锁索引记录,例如:

select * from t where id=1 for update;

它会在id=1的索引记录上加锁,以阻止其他事务插入,更新,删除id=1的这一行。

需要说明的是:

select * from t where id=1;

是快照读(SnapShot Read),它并不加锁

第六种,间隙锁(Gap Locks)

建表和初始化语句如下:

CREATE TABLE `t` (

`id` int(11) NOT NULL,

`c` int(11) DEFAULT NULL,

`d` int(11) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `c` (`c`)

) ENGINE=InnoDB;

insert into t values(0,0,0),(5,5,5),

(10,10,10),(15,15,15),(20,20,20),(25,25,25);

这个表除了主键id外,还有一个索引c

为了解决幻读问题,InnoDB引入了间隙锁,锁的就是两个值之间的空隙

当执行select * from t where d=5 for update的时候,就不止是给数据库中已有的6个记录加上了行锁,还同时加了7个间隙锁。这样就确保了无法再插入新的记录

行锁分成读锁和写锁

跟间隙锁存在冲突关系的是往这个间隙中插入一个记录这个操作。间隙锁之间不存在冲突关系

这里sessionB并不会被堵住。因为表t里面并没有c=7会这个记录,因此sessionA加的是间隙锁(5,10)。而sessionB也是在这个间隙加的间隙锁。它们用共同的目标,保护这个间隙,不允许插入值。但它们之间是不冲突的

间隙锁和行锁合称next-key lock,每个next-key lock是前开后闭区间。表t初始化以后,如果用select * from t for update要把整个表所有记录锁起来,就形成了7个next-key lock,分别是(-∞,0]、(0,5]、(5,10]、(10,15]、(15,20]、(20, 25]、(25, +supremum]。因为+∞是开区间,在实现上,InnoDB给每个索引加了一个不存在的最大值supremum,这样才符合都是前开后闭区间

间隙锁和next-key lock的引入,解决了幻读的问题,但同时也带来了一些困扰

间隙锁导致的死锁:

1.sessionA执行select … for update语句,由于id=9这一行并不存在,因此会加上间隙锁(5,10)

2.sessionB执行select … for update语句,同样会加上间隙锁(5,10),间隙锁之间不会冲突

3.sessionB试图插入一行(9,9,9),被sessionA的间隙锁挡住了,只好进入等待

4.sessionA试图插入一行(9,9,9),被sessionB的间隙锁挡住了

两个session进入互相等待状态,形成了死锁

间隙锁的引入可能会导致同样的语句锁住更大的范围,这其实是影响并发度的

在读提交隔离级别下,不存在间隙锁

第七种,临键锁(Next-Key Locks)

临键锁,是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。

更具体的,临键锁会封锁索引记录本身,以及索引记录之前的区间。

如果一个会话占有了索引记录R的共享/排他锁,其他会话不能立刻在R之前的区间插入新的索引记录。

t(id PK, name KEY, sex, flag);

表中有四条记录:

1, songliu, m, A

3, zhangsan, m, A

5, lisi, m, A

9, wangwu, f, B

PK上潜在的临键锁为:

(-infinity, 1]

(1, 3]

(3, 5]

(5, 9]

(9, +infinity)

临键锁的主要目的,也是为了避免幻读(Phantom Read)。如果把事务的隔离级别降级为RC,临键锁则也会失效。

【总结】

(1)自增锁(Auto-inc Locks):表级锁,专门针对事务插入AUTO_INC的列,如果插入位置冲突,多个事务会阻塞,以保证数据一致性;

(2)共享/排它锁(Shared and Exclusive Locks):行级锁,S锁与X锁,强锁;

(3)意向锁(Intention Locks):表级锁,IS锁与IX锁,弱锁,仅仅表明意向;

(4)插入意向锁(Insert Intention Locks):针对insert的,如果插入位置不冲突,多个事务不会阻塞,以提高插入并发;

(5)记录锁(Record Locks):索引记录上加锁,对索引记录实施互斥,以保证数据一致性;

(6)间隙锁(Gap Locks):封锁索引记录中间的间隔,在RR下有效,防止间隔中被其他事务插入;

(7)临键锁(Next-key Locks):封锁索引记录,以及索引记录中间的间隔,在RR下有效,防止幻读;

来源地址:https://blog.csdn.net/songmulin/article/details/128650209

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Mysql七种锁

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

2023-09-05

MySQL:七种 SQL JOINS 的实现(图文详解)

MySQL:7种SQL JOINS的实现 前言一、图示表示二、代码举例1、INNER JOIN(内连接)2、LEFT JOIN(左连接)3、RIGHT JOIN(右连接)4、OUTER JOIN(全连接)5、LEFT EXCLUDI
2023-08-16

mysql查询(七)

查询学过「张三」老师授课的同学的信息多表联合查询      and(和)第一种:命令:select ex_xueshengbiao_95.Sid,ex_xueshengbiao_95.Sname,ex_xueshengbiao_95.Sage,ex_xuesh
mysql查询(七)
2019-06-09

MySQL第七课

统计记录条数SELECT COUNT(*)  FROM 表名;SUM():总和AVG():平均值MAX():最大值MIN():最小值  排序:SELECT 字段名  FROM 表名ORDER BY 字段名1[ASC/DESC] ,字段名2[ASC/DESC];
MySQL第七课
2019-04-05

MySQL基础扎实——MySQL中有哪几种锁

常见锁举例 在MySQL中,常见的锁包括以下几种: 表级锁(Table-level Lock):表级锁是对整张表进行锁定,可以分为两种类型: 共享锁(Shared Lock):也称为读锁(Read Lock),多个事务可以同时持有共
2023-08-30

MySQL查询性能优化七种方式索引潜水

这篇文章主要介绍了MySQL查询性能优化七种方式索引潜水,文章为荣啊主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
2022-11-13

mysql表级锁的模式有几种

本篇内容介绍了“mysql表级锁的模式有几种”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、表共享读锁,添加共享读锁的表不会阻塞其他ses
2023-06-20

怎样深入理解mysql各种锁

怎样深入理解mysql各种锁,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。锁的概述锁是计算机协调多个进程或线程并访问某一资源的机制在数据库中,除传统的计算机资源(如cpu、RA
2023-06-21

MySQL内连接和外连接及七种SQLJOINS的实现

这篇文章主要介绍了Mysql内连接和外连接的区别以及七种SQLJoins的实现,相信看完这篇文章你对SQL内外连接的多表查询就足够理解了,需要的朋友可以参考下
2023-03-23

Vista破解激活七种方法

1、替换法 原理:用替换vista的一些许可文件的办法来用测试版序列号激活vista,是最早出现的办法 缺点:许可变为测试版,有时间限制 2、kms私服激活法 原理:不是去微软的官方服务器激活,而是去私人架设的服务器激活,也可以用vmwar
2023-05-24

MySQL索引概念及七种索引类型分享介绍

目录1 索引的概念2 索引的类型1 索引的概念索引(在mysql中也叫做“键(key)”)是存储引擎用于快速找到记录的一种数据结构,这也是索引最基本的功能。索引对于良好的性能非常关键。数据量越大时,索引对性能的影
2022-08-22

编程热搜

目录