网易首页 > 网易号 > 正文 申请入驻

Mysql的死锁与索引的关系

0
分享至

前言

在工作过程中,我们经常会碰到mysql的死锁问题,也是我们非常头疼的问题,今天老顾尝试着和小伙伴们一起学习一下mysql锁的相关知识点。

锁分类

我们经常说的就是 表锁、以及行锁

表锁:对整张表加锁
行锁:对表中的某条记录加锁

mysql数据库引擎支持的锁类型是不同的

  • MyISAM 只支持到表级锁
  • InnoDB 可以支持到行级锁

表锁

对整张表加锁,锁的颗粒度大,资源消耗小,并发请求低;表锁有2种模式:

1、表共享锁:对同一表的不阻塞读,但阻塞写。

2、表独占锁:对同一表的操作,不管是读写,都阻塞。

共享锁

独占锁

共享锁

兼容

冲突

独占锁

冲突

冲突

显式加表锁:lock tables {tb_name} read/write显式释放锁:unlock tables

行锁

我们今天的重点就是行锁,也就是死锁的根源所在。行级别的锁颗粒度小,开销比较大

锁模式:

1、共享锁(读锁)S锁:对同一行的操作,读不阻塞,写阻塞

2、排他锁(写锁)X锁:对同一行的操作,读写都阻塞

3、意向共享锁IS:一个事务想要加S锁,首先先获得该表的IS锁

4、意向排他锁IX:一个事务想要加X锁,首先先获得该表的IX锁

意向锁本质就是表锁,那为什么要有意向锁呢?
意向锁用来标识该表上有数据被加锁或将被加锁,对于表级别的请求(lock table....),就可以直接判断是否有锁冲突,不需要逐行检查锁的状态

S锁

X锁

IS锁

IX锁

S锁

兼容

冲突

兼容

冲突

X锁

冲突

冲突

冲突

冲突

IS锁

兼容

冲突

兼容

兼容

IX锁

冲突

冲突

兼容

兼容

InnoDB锁方式

InnoDb的默认隔离级别RR(可重复读),在RR下读取数据的方式:

1、快照读:事务开启执行第一个SELECT语句后会获取一个数据快照,直到事物结束读取到的数据都是一致的

普通的 select… 查询都是快照读

2、当前读:读取的数据的最新版本,并且在读的时候不允许其它事物修改当前记录

select… lock in share mode(S锁)select… for update(X锁)

加锁方式:

  • 普通 select… 查询 (不加锁)
  • 普通 insert、update、delete… (隐式加写锁)
  • select…lock in share mode (加读锁)
  • select…for update (加写锁)

解锁方式:

  • 提交/回滚事物(commit/rollback)
  • kill 阻塞进程

锁与索引

InnoDB的行锁是通过给索引上的索引项加锁来实现

即使在建表的时候没有指定主键,InnoDB会默认创建一个DB_ROW_ID的自增字段为表的主键,并且其主键索引(聚簇索引)为GEN_CLUST_INDEX
主键索引也被称为聚簇索引

行锁类型

  • Record Lock: 对对应的索引记录项加锁,称记录锁
  • Gap Lock:对索引项之间的间隙加锁,加锁之后间隙范围内不允许插入数据,防止发生幻读
  • Next-key Lock:可以理解为Record Lock+Gap Lock(InnoDB行锁默认加的是 Next-key Lock)

记录锁

这个比较好理解,就是把表中的记录锁定。

间隙锁

编程的思想源于生活,生活中的例子能帮助我们更好的理解一些编程中的思想。

生活中排队的场景,小明,小红,小花三个人依次站成一排,此时,如何让新来的小刚不能站在小红旁边,这时候只要将小红和她前面的小明之间的空隙封锁,将小红和她后面的小花之间的空隙封锁,那么小刚就不能站到小红的旁边。

这里的小红,小明,小花,小刚就是数据库的一条条记录。

他们之间的空隙也就是间隙,而封锁他们之间距离的锁,叫做间隙锁。

加锁规则

行级锁默认加 next-key lock,查询过程中访问到的索引项都会加锁,而根据不同的索引也有不同的加锁规则

唯一索引等值查询:

当索引项存在时,next-key lock 退化为 record lock;

当索引项不存在时,默认 next-key lock,访问到不满足条件的第一个值后next-key lock退化成gap lock

唯一索引范围查询:

默认 next-key lock,(特殊’<=’ 范围查询直到访问不满足条件的第一个值为止)

非唯一索引等值查询:

默认next-key lock ,索引项存在/不存在都是访问到不满足条件的第一个值后next-key lock退化成gap lock

非唯一索引范围查询:

默认 next-key lock,向右访问到不满足条件的第一个值为止

针对这几种情况分别举例说明一下,假设我有以下数据:

id

name

age

1

张三

21

4

王一

26

6

小军

18

9

小红

23

在上面的数据表我们可以得到5个next-key lock 区间:

唯一索引(id):(-∞,1],(1,4],(4,6],(6,9] ,(9,+supremum]

非唯一索引(age):(-∞,18],(18,21],(21,23],(23,26] ,(26,+supremum]

案例:唯一索引等值查询

索引项存在

eg:select * from user where id=4 for update

加锁情况:

默认加next-key lock (1,4],因索引项存在,则next-key lock退化为 record key,只对id=4的这个索引项的record key

索引项不存在

eg:select * from user where id=5 for update

加锁情况:

默认加next-key lock (4,6],访问不满足条件id=6后next-key lock退化为grap lock,加锁范围(4,6)

案例:唯一索引范围查询

eg: '>'select * from user where id > 4 for update

加锁情况:默认next-key lock (4,6],(6,9],(9,+suprenum]

eg: '<'select * from user where id < 4 for update

加锁情况:默认next-key lock (-∞,1],(1,4]

eg: '>=' (可以拆成 > 和 =)select * from user where id >= 4 for update

加锁情况:

'>4': 范围查询 默认next-key lock (4,6],(6,9],(9,+suprenum]

'=4': 等值查询 默认next-key lock退化为record key,id=4的索引项

‘>=4’: 合并在一起加锁范围为:[4,6],(6,9],(9,+suprenum]

eg: '<='(可以拆成 < 和 =)select * from user where id <= 4 for update

加锁情况:

‘<4’: 范围查询 默认next-key lock (-∞,1],(1,4],这里有点特殊范围查询,需要访问不满足条件(<=4)的第一个值为止,因此找到了6;加锁范围 (-∞,1],(1,4],(4,6]

'=4': 等值查询 默认next-key lock退化为record key,id=4的索引项

‘<=4’: 合并在一起加锁范围为:(-∞,1],(1,4],(4,6]

案例:非唯一索引等值查询

索引项存在

eg:select * from user where age=21 lock in share model

加锁情况:

默认加next-key lock (18,21], (21,23];

访问到不满足条件age=23后next-key lock退化为grap key

加锁范围(18,21], (21,23)

索引项不存在

eg:select * from user where age=19 lock in share model

加锁情况:

默认加next-key lock (18,21],

访问不满足条件age=21后next-key lock退化为grap lock

加锁范围(18,21)

案例:非唯一索引范围查询

eg:'>'select * from user where age > 21 lock in share model

加锁情况:

默认加next-key lock (18,21], (21,23],(23,26], (26,+suprenum],

向右访问到不满足条件第一个值为止 (18,21], (21,23],(23,26], (26,+suprenum]

加锁范围 (18,21], (21,23],(23,26], (26,+suprenum]

eg:'<'select * from user where age < 21 lock in share model

加锁情况:

默认加next-key lock (-∞,18], (18,21],

向右访问到不满足条件第一个值为止 (-∞,18], (18,21],(21,23]

加锁范围 (-∞,18], (18,21],(21,23]

eg:'>=' (可以拆成 > 和 =)select * from user where age >= 21 lock in share model

加锁情况:

‘> 21 ’ 范围查询 (18,21], (21,23],(23,26], (26,+suprenum]

'= 21' 等值查询 (18,21], (21,23)

合并加锁范围 (18,21],(21,23],(23,26], (26,+suprenum]

eg:'<='(可以拆成 < 和 =)select * from user where age < 21 lock in share model

加锁情况:

‘< 21 ’: 范围查询 (-∞,18], (18,21], (21,23]

‘= 21 ’: 等值查询 (18,21], (21,23)

合并加锁范围 (-∞,18], (18,21],(21,23]

细心一点你会发现上面例子中:

唯一索引的查询用的是 select … for update
非唯一索引的查询用的是 select … lock in share model

for update 加的是写锁,写锁默认认为会对数据做更改,不管查询有没有涉及到回表都会对聚簇索引(主键索引)加锁lock in share model 加的是读锁,如果没有涉及到回表(像覆盖索引),不会对聚簇索引(主键索引)加锁

如果上面例子中非唯一索引的查询用的是 select … for update,还需要分析聚簇索引(主键索引)的加锁情况(可参考文章
https://www.jianshu.com/p/bf862c37c4c9)

死锁

死锁指的是两个或两个以上的事物在执行过程中争抢锁资源而造成相互等待的情况

表锁不会出现死锁,主要还是针对InooDB的行锁,可以看下面的例子:

会话A与会话B 互相产生了死锁。

监控分析锁问题

# 查询InnoDB锁的整体情况# 可以重点查看Innodb_row_lock_waits和Innodb_row_lock_time_avg这两个值# 如果数值较大,说明锁之间的竞争大show status like 'innodb_row_lock%';#可以通过INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS这三个表#分析可能存在的锁的问题select * from information_schema.INNODB_TRX; # 查看所有事务select * from information_schema.INNODB_LOCKS; # 查看锁select * from information_schema.INNODB_LOCK_WAITS; # 查看锁等待

解决死锁:

超时等待,事物超时自动回滚(innodb_lock_wait_timeout 默认50s)

主动死锁检测,事物请求锁的时候采用 wait-for graph 等待图的方式进行死锁检测(innodb_deadlock_detect 默认on)

发现死锁也可以人为 kill 进程

总结

  • MySQL锁分为全局锁、表级锁以及行级锁,不同的存储引擎支持锁的粒度有所不同,MyISAM 只支持到表级锁,InnoDB 则可以支持到行级锁,锁的粒度决定了业务的并发度,因此更推荐使用InnoDB
  • InnoDB默认最小加锁粒度为行级锁,并且锁是加在索引上,如果SQL语句未命中索引,则走聚簇索引的全表扫描,表上每条记录都会上锁,导致并发能力下降,增大死锁的概率,因此需要为表合理的添加索引,线上查询尽量命中索引
  • 行级锁默认加 next-key lock,而根据不同的索引也有不同的加锁规则,我们可以根据加锁规分析加锁区间
  • 锁粒度的减小提高了并发度的同时也增加了死锁的风险,查询应尽量考虑减少锁的范围

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
基因无法骗人!看《爸去哪儿》7位萌娃,10年后颜值差距一目了然

基因无法骗人!看《爸去哪儿》7位萌娃,10年后颜值差距一目了然

贾文彬的史书
2024-06-15 20:34:59
头条欧洲杯|老将见证新星闪耀,球场上,岁月不饶人

头条欧洲杯|老将见证新星闪耀,球场上,岁月不饶人

澎湃新闻
2024-06-16 08:14:35
女生私密「小花瓣」形状到底什么样,才算正常

女生私密「小花瓣」形状到底什么样,才算正常

水白头
2024-06-15 01:35:03
俄杜马主席:一些乌议员已开始讨论普京停火提议

俄杜马主席:一些乌议员已开始讨论普京停火提议

参考消息
2024-06-15 19:12:10
068期双色球之解析,惊喜6+1,蓝定10,11,3区防26,28,33

068期双色球之解析,惊喜6+1,蓝定10,11,3区防26,28,33

王晓爱体彩
2024-06-16 11:45:05
降薪850万,重签快船!伤病毁了小卡的生涯,三巨头解体或难改变

降薪850万,重签快船!伤病毁了小卡的生涯,三巨头解体或难改变

呆哥聊球
2024-06-16 12:28:04
不婚族万茜:从不炒作,嫁普通丈夫,40岁高龄为小丈夫生孩子

不婚族万茜:从不炒作,嫁普通丈夫,40岁高龄为小丈夫生孩子

谈娱新语
2024-06-15 22:11:33
养老金上调基本正式确定,1950和1960出生的人,上调会有差异吗?

养老金上调基本正式确定,1950和1960出生的人,上调会有差异吗?

奇名呀
2024-06-11 09:02:33
G7发布联合声明,不许中国援俄,不许武力收台,也不许反制菲律宾

G7发布联合声明,不许中国援俄,不许武力收台,也不许反制菲律宾

战域笔墨
2024-06-16 13:04:09
河南64岁大爷五年间染指55名女性,只因太了解女性心理

河南64岁大爷五年间染指55名女性,只因太了解女性心理

真实故事汇
2024-05-06 13:31:30
江苏:女子与“光头强”相亲,直言越看越喜欢,女子:我比他有钱

江苏:女子与“光头强”相亲,直言越看越喜欢,女子:我比他有钱

深月望城
2024-06-12 18:02:47
妻子出轨男闺蜜,以为神不知鬼不觉,母亲60大寿丈夫送上“惊喜”

妻子出轨男闺蜜,以为神不知鬼不觉,母亲60大寿丈夫送上“惊喜”

星辰故事屋
2024-06-10 15:45:17
大瓜!又有网友自曝给王思聪生孩子,称万达长孙,喊话不想再忍了

大瓜!又有网友自曝给王思聪生孩子,称万达长孙,喊话不想再忍了

拾娱先生
2024-06-15 22:05:08
“他下周将赴中国,预计会激烈磋商”

“他下周将赴中国,预计会激烈磋商”

观察者网
2024-06-16 10:46:18
演员邓超突然发声!

演员邓超突然发声!

娱记掌门
2024-06-13 10:07:52
我可以东契奇总决赛G4主防凯尔特人球员时 对手合计11中2

我可以东契奇总决赛G4主防凯尔特人球员时 对手合计11中2

直播吧
2024-06-16 13:20:10
以色列把真主党的2号领导送“走”了

以色列把真主党的2号领导送“走”了

近距离
2024-06-14 19:28:25
父亲头七刚过,分家产时养女自觉离开,上火车时却被哥嫂跩下来

父亲头七刚过,分家产时养女自觉离开,上火车时却被哥嫂跩下来

娱乐洞察点点
2024-06-03 16:54:38
许亚军:我结四次婚,并不是因为我花心,只是对婚姻负责任

许亚军:我结四次婚,并不是因为我花心,只是对婚姻负责任

番茄说史聊
2024-06-15 21:24:59
美媒:关于海权,中国跟我们的理解并不相同

美媒:关于海权,中国跟我们的理解并不相同

环球时报国际
2024-06-15 06:55:18
2024-06-16 13:52:49
有趣黑科技
有趣黑科技
生活中你不知道的黑科技
820文章数 124757关注度
往期回顾 全部

科技要闻

iPhone 16会杀死大模型APP吗?

头条要闻

上海一家三口出动去香港过周末 在高铁动卧睡一晚就到

头条要闻

上海一家三口出动去香港过周末 在高铁动卧睡一晚就到

体育要闻

没人永远年轻 但青春如此无敌还是离谱了些

娱乐要闻

上影节红毯:倪妮好松弛,娜扎吸睛

财经要闻

打断妻子多根肋骨 上市公司创始人被公诉

汽车要闻

售17.68万-21.68万元 极狐阿尔法S5正式上市

态度原创

房产
教育
健康
手机
公开课

房产要闻

万华对面!海口今年首宗超百亩宅地,重磅挂出!

教育要闻

视频 | 山东夏季高考试卷总数404.2万份,记者带您探访评卷现场

晚餐不吃or吃七分饱,哪种更减肥?

手机要闻

华为Pura 70系列推送鸿蒙OS 4.2 167版升级:优化相机 拍月亮更强

公开课

近视只是视力差?小心并发症

无障碍浏览 进入关怀版