前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL锁

MySQL锁

作者头像
jeanron100
发布2019-06-22 20:10:05
1K0
发布2019-06-22 20:10:05
举报
文章被收录于专栏:杨建荣的学习笔记

这是学习笔记的第 2015 篇文章

今天引用一下我书稿中的一部分内容,关于锁的东东。

InnoDB的锁,实现了两种类型的行锁。

l 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同的数据集的排他锁。

select * from table_name where .....lock in share mode

l 排他锁(X):允许获得排他锁的事务更新数据,但是组织其他事务获得相同数据集的共享锁和排他锁。

select * from table_name where .....for update

在此我们可以设想一个场景,有两个事务A和B,事务A锁住了表中的一行,加了行锁S,即这一行只能读不能写。

之后事务B申请整个表的写锁(MySQL Server层可以使用lock table xxxx write的方式加写锁锁表),那么理论上它就能修改表中的任意一行,包括共享锁S锁定的那一行,这种情况下和事务A持有的行锁是冲突的,这种情况下,就需要有一种机制来判断,避免这个冲突,比如我们需要先判断表是否被其他事务用表锁锁定,然后判断表中的每一行是否被行锁锁住,显然这种情况下是不可接受的,问题的瓶颈就在于需要遍历整个表,随着数据量的增加,这个代价就会无限放大,在这种情况下,意向锁就是来做这个冲突协调者的。

所以一个正常的流程就会变为:

l 事务A必须先申请表的意向共享锁,成功后申请一行的行锁

l 事务B申请排它锁,但是发现表上已经有意向共享锁,说明表中的某些行已经被共享锁锁定了,事务B申请写锁的操作会被阻塞。

而这也是为什么需要表级意向锁的主要原因,InnoDB有两个表级意向锁:

l 意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁

l 意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。

整个表级意向锁的加锁过程是自动完成的,我们可以举个例子来说明下,比如我们生活中的红绿灯,一般路灯红绿灯切换是不会马上切换的,而是会转为黄色,转为黄色后,会有几秒钟的缓冲时间,而这些就是留给了行人和司机的准备时间,表级意向锁的角色和这个是类似的。

说完表级意向锁,我们继续来说行锁。

InnoDB行锁是通过给索引项加锁实现的,如果没有索引,InnoDB会通过隐藏的聚簇索引来对记录加锁。

如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。

InnoDB支持如下的三种行锁定方式:

l Record lock:对索引项加锁,即锁定一条记录;

l Gap lock:对索引项之间的‘间隙’、对第一条记录前的间隙或最后一条记录后的间隙加锁,即锁定一个范围的记录,不包含记录本身;

l Next-key Lock:锁定一个范围的记录并包含记录本身。

Next-Key Lock是行锁与间隙锁的组合,当InnoDB扫描索引记录的时候,会首先对选中的索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。如果一个间隙被事务加了锁,其它事务是不能在这个间隙插入记录的。

到目前为止,我们也说了几种锁了,这些锁之间是什么样的兼容关系,可能有的同学会有些迷糊,MySQL里的锁兼容列表大体是这样的关系,我们需要明确:意向锁之间是互相兼容的,这句话很重要。按照这个思路里面一半的内容就明确了。而另外一部分则是S和X的兼容性。带着S锁和X锁的组合都是互相排斥,而S锁之间是互相兼容的。所以下图7-10按照这个思路几乎不用记就能基本理解了。

此外就是死锁,如果锁不兼容的情况下,通常会产生阻塞,而如果产生互相阻塞的场景,那就是死锁了。

如图所示,这是一种经典的死锁检测机制:wait-for graph算法

我们来看一个死锁的小例子,在两个会话并发的场景下,死锁的步骤如下:

首先创建一张表dt1,语句如下:

create table dt1 (id int unique);

然后按照下表的方式来操作。

时间

session1

session2

T1

begin;select *from dt1 lock in share mode;

T2

begin;select *from dt1 lock in share mode;

T3

insert into dt1 values(1); --阻塞

T4

insert into dt1 values(2); 产生死锁

所以上面的语句特点很明显,插入的数据分别是1和2产生了死锁,我们可能很少看到直接声明share mode的方式,但是有很多时候由其他的场景会触发,比如对于duplicate数据的检查会开启S锁。这是比较特别的一点,需要注意。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档