MySQL-InnoDB行锁
InnoDB的锁类型
InnoDB存储引擎支持行锁,锁类型有两种:
- 共享锁(S锁)
- 排他锁(X锁)
S和S不互斥,其他均互斥。
除了这两种锁以外,innodb还支持一种锁,叫做意向锁。
那么什么是意向锁?为什么需要意向锁呢?
考虑这种情况:
SessionA:已经持有表t某一行的X锁,需要对行进行更新操作
SessionB:想申请表t的表锁写锁
在没有意向锁之前,SessionA已经持有了行X锁以后,如果SessionB也成功,意味着SessionB可以对这个表中的所有数据进行更新操作,与SessionA的行锁是冲突的。
所以数据库在同意SessionB的申请之前,会做以下的判断:
- 检查是否有其他的表级写锁存在
- 判断表中每一行是否有行级X锁存在
步骤2的判断本身效率不高。所以产生了意向锁,在申请行级锁之前,先申请意向锁,成功之后才能申请行锁。(简单理解为多保存一个变量,便于申请表锁的时候进行快速判断)。
意向锁分为两种:
- 意向共享锁(IS锁)
- 意向排他锁(iX锁)
IS锁和IX锁之间彼此都不互斥,IS和IX只和表级别的读写锁互斥。其中:
- IX和表X和表S互斥
- IS和表X互斥
一致性锁定读和一致性非锁定读
一致性非锁定读
当隔离类型设置为读已提交和可重复读时,我们写的普通的select语句,不会申请锁,也不会被阻塞,会从MVCC选择一个视图读取数据。
两种隔离状态的区别在于:
- 读已提交永远拿到的是最新的视图
- 可重复读永远使用事务刚建立时拿到的视图
一致性锁定读
当写这两种select语句时,会进行加锁操作。
- select ... lock in share mode
- 这个语句表示加入一个S锁,其他事务也可以加S锁
- 使用场景:不同表之间的相同数据保持一致性时使用(存疑,暂时放着)
- select ... for update
- 这个语句表示加入一个X锁,其他事务不能读也不能写
- 使用场景:先读,根据读结果进行修改的操作时可以使用
行锁的三种算法(判断锁定的范围)
InnoDB存储引擎有三种行锁的锁定算法:
- record lock:锁定单行
- gap lock:锁定范围,不包含记录本身
- next-key lock:gap lock + record lock 既锁定范围又锁定记录本身
当select操作需要加锁时,会按照上面的next-key lock进行加锁。
- 当查询条件中有索引,并且是唯一索引时,可以只锁定单条记录,由next-key lock降级为 record lock。
- 当查询条件中有索引,并且索引是辅助索引时,不仅锁住记录本身,还会锁定记录前一个索引键值范围(不包括区间头部的值),除此之外,还会锁定记录值到下一个索引键值的范围(不包括区间尾端的值);同时还会在主键索引的对应行上加record lock
实验验证
输入下列建表语句:
create table z(a int,b int,primary key(a),key(b));
insert into z select 1,1;
insert into z select 3,1;
insert into z select 5,3;
insert into z select 7,6;
insert into z select 10,8;
在sessionA中,输入下面查询语句
select * from z where b=3 for update;
在sessionB中,输入下面查询语句
select * from z where b=1 for update;
select * from z where b=3 for update;
insert into z (a,b) values(4,2);
select * from z where b=6 for update;
其中,第一条和第四条可以正常返回,第二条第三条语句会阻塞,因为SessionA一直没有commit,所以这两条语句阻塞一段时间后会报锁等待超时异常。
mysql> select * from z where b=1 for update;
+---+------+
| a | b |
+---+------+
| 1 | 1 |
| 3 | 1 |
+---+------+
2 rows in set (0.00 sec)
mysql> select * from z where b=6 for update;
+---+------+
| a | b |
+---+------+
| 7 | 6 |
+---+------+
1 row in set (0.00 sec)
mysql> select * from z where b=3 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into z (a,b) values(4,2);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
结果分析
查询条件为b=3,所以会使用b列的辅助索引来查询,找到记录3后
- 使用record lock锁定主键索引a=5的记录
- 使用next-key lock锁定辅助索引(1,3)3 (3,6)这个范围的记录
在SessionA提交事务之前,这个范围内的记录都加的是X排他锁,所以第二条和第三条记录都需要阻塞等待。
MySQL-InnoDB行锁的更多相关文章
- Mysql InnoDB行锁实现方式(转)
Mysql InnoDB行锁实现方式 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点 ...
- Mysql InnoDB行锁实现方式
Mysql InnoDB行锁实现方式 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点 ...
- Mysql InnoDB行锁不使用索引锁表的时候会锁整张表
原文:http://www.thinkphp.cn/topic/41577.html 如果使用针对InnoDB的表使用行锁,被锁定字段不是主键,也没有针对它建立索引的话.行锁锁定的也是整张表.锁整张表 ...
- Mysql研磨之InnoDB行锁模式
事务并发带来的一些问题 (1)更新丢失(LostUpdate):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题最后的更新覆盖了由其 ...
- MySQL锁---InnoDB行锁需要注意的细节
前言 换了工作之后,接近半年没有发博客了(一直加班),emmmm.....今天好不容易有时间,记录下工作中遇到的一些问题,接下来应该重拾知识点了.因为新公司工作中MySQL库经常出现查询慢,锁等待,节 ...
- MySQL锁:03.InnoDB行锁
目录 InnoDB 行锁 锁排查可以用的视图和数据字典 InnoDB 行锁兼容性 InnoDB行锁之共享锁 共享锁: 查看InnoDB锁 InnoDB行锁实现机制 对普通索引上锁 InnoDB隐式.显 ...
- mysql 开发进阶篇系列 9 锁问题 (Innodb 行锁实现方式)
一.概述 Innodb 行锁是通过给索引上的索引项加锁来实现的.这一点与(oracle,sql server)不同后者是通过在数据块中对相应的数据行加锁.这意味着只有通过索引条件检索数据,innodb ...
- Innodb行锁源码学习(一)
Innodb是mysql数据库中目前最流行的存储引擎,innodb相对其它存储引擎一个很大的特点是支持事务,并且支持行粒度的锁.今天我重点跟大家分享下innodb行锁实现的基础知识.由于篇幅比较大,文 ...
- 巧用MySQL InnoDB引擎锁机制解决死锁问题(转)
该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深 ...
- MySQL InnoDB引擎锁的总结
为什么要锁 我们开的的各式各样系统中,系统运行需要CPU.内存.I/O.磁盘等等资源.但除了硬资源外,还有最为重要的软资源:数据. 当人们访问操作我们的系统时,其实归根是对数据的查看与生产.那么对于同 ...
随机推荐
- IIS通过URL重写配置http跳转https,排除部分域名
<rewrite> <rules> <rule name="http to https" stopProcessing="true" ...
- asp.net mvc中换肤机制类库 ThemedViewEngines
制作blog系统或者通用cms系统的时候,我们经常会用到Theme功能.asp.net mvc中的一种实现方式,是继承实现RazorViewEngine即可. 这是在GitHub中找到的一个示例:ht ...
- 一个R包—reticulate—在R中调用Python
R语言和python语言是生信行业经常使用的两个计算机语言,R语言具有统计和画图方面的优势,但是R语言在文件读写上的速度实在不敢恭维:Python具有较快的文件读写功能,但是其统计和画图却不如R语言用 ...
- Map中经常被忽略但又非常好用的方法
1. 简介 map是我们日常开发中常会的集合类之一, 但是我们除了常用的get和put之外,其他的方法好像很少会用到,接下来我们就介绍一下几个经常被忽略但又很好用的方法. 2. Quick Start ...
- weixueyuan-Nginx代理服务器5
https://www.weixueyuan.net/nginx/proxy_server/ Nginx HTTP代理服务器 代理功能根据应用方式的不同可以分为正向代理和反向代理.正向代理是客户端设置 ...
- flutter如何搭建android环境
1.电脑上按安装sdk 首先配置Java的JDK 配好后,输入java 出现内容说明安装成功 然后在输入javac 出现内容说明jre安装成功 2.电脑上安装android Studio 安卓下载地址 ...
- 微信小程序如何更改appid
每一个吧小程序对应唯一一个appid; 但是在有些时候,我们需要更改appid; 点击详情,小程序右侧会出现下面的弹窗: 此时我们可以看见修改appid 这里修改了,才是真正的修改了: 这样我们上传微 ...
- 第2章 C# 语言基础
第2章 C# 语言基础 难点提纲 mindmap 第2章 C#语言基础 数值类型 数值字面量 溢出检查 特殊的浮点值 decimal 舍入误差 数组 简化初始化的<br/>两种方式 变量和 ...
- 600条Linux 命令总结
一.基本命令 uname -m 显示机器的处理器架构 uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 (SMBIOS / DMI) hdparm -i /de ...
- docker搭建rabbitmq镜像集群
Rabbitmq普通集群模式,是将交换机.绑定.队列的元数据复制到集群里的任何一个节点,但队列内容只存在于特定的节点中,客户端通过连接集群中任意一个节点,即可以生产和消费集群中的任何队列内容(因为每个 ...