当前位置: 首页 > news >正文

MySQL锁

这是学习笔记的第 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按照这个思路几乎不用记就能基本理解了。

640?wx_fmt=jpeg

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

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

640?wx_fmt=png

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

首先创建一张表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锁。这是比较特别的一点,需要注意。

640?

相关文章:

  • 难忘的三件苦差事
  • 千与千寻,真是一部给大人看的动画片
  • 聊聊高考分数线和选择
  • MySQL中间件的连接错误问题排查
  • 一次宕机问题的总结复盘
  • 所谓简单的事情
  • 数据分析上千部动漫作品
  • 生活中的一些文字调料
  • 最近的方向调整
  • 尴尬的bug:一条查询语句让MySQL崩溃
  • 你平时锻炼身体吗
  • 数据迁移流程的优化
  • MySQL复制问题的分析
  • 秦皇岛旅游归来
  • 《MySQL DBA工作笔记》前言
  • Git的一些常用操作
  • Git学习与使用心得(1)—— 初始化
  • HTTP中GET与POST的区别 99%的错误认识
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • Koa2 之文件上传下载
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • MobX
  • Netty源码解析1-Buffer
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • STAR法则
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 百度小程序遇到的问题
  • 理清楚Vue的结构
  • 聊聊flink的BlobWriter
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 前端代码风格自动化系列(二)之Commitlint
  • 如何利用MongoDB打造TOP榜小程序
  • 数据结构java版之冒泡排序及优化
  • 通信类
  • 线上 python http server profile 实践
  • 学习笔记:对象,原型和继承(1)
  • 《天龙八部3D》Unity技术方案揭秘
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​学习一下,什么是预包装食品?​
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • (8)STL算法之替换
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (Note)C++中的继承方式
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (二)hibernate配置管理
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (三分钟)速览传统边缘检测算子
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)winform之ListView
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET(C#) Internals: as a developer, .net framework in my eyes