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.磁盘等等资源.但除了硬资源外,还有最为重要的软资源:数据. 当人们访问操作我们的系统时,其实归根是对数据的查看与生产.那么对于同 ...
随机推荐
- 在Quartz .NET的工作类中使用依赖注入
Quartz .NET默认的Execute方法是不支持非空的构造函数的,所以.net core常用的构造函数依赖注入也搞不来,网上搜索一番搞定了这个问题. 解决方案简单来说就是自定义一个任务工厂,替换 ...
- 为什么要把数据模型分为:Entity,DTO,Response,Request呢?具体有什么作用呢
开发中,我们通常把数据模型分为几个部分,探讨下他们具体都有那些作用. 1. Entity(实体) 实体类代表数据库表结构,与数据库表一一对应. // 例如 User.cs public class U ...
- WPF 取消在触屏上点击按下不松开会出现矩形背景的效果
加个属性: btn.SetValue(Stylus.IsPressAndHoldEnabledProperty,false); 或者在样式里设置: <Style x:Key="MyB ...
- HiJobQueue:一个简单的线程安全任务队列
HiJobQueue:一个简单的线程安全任务队列 概述 HiJobQueue 是一个线程安全的任务队列,用于在多线程环境中管理和执行异步任务.它的设计参考了 Cobalt 项目中的 JobQueue, ...
- [译] WinForms:分析一下(我用 Visual Basic 写的)
原文 | Klaus Loeffelmann 翻译 | 郑子铭 如果您从未看过电影<分析这一点>,下面是简短的介绍:假设一个纽约家族的成员有可疑的习惯,他决定认真考虑接受治疗以改善他的精神 ...
- ORACLE11g数据中创建DB Link方法,用于跨oracle数据库查询数据
---查看该用户下已建立的DB link链接 SELECT * FROM DBA_DB_LINKS --创建语句 CREATE DATABASE LINK 连接名CONNECT TO 登录名 ID ...
- Codeforces 1536B Prinzessin der Verurteilung 题解 [ 紫 ] [ 后缀自动机 ] [ 动态规划 ] [ 拓扑排序 ]
Prinzessin der Verurteilung:最短未出现字符串的板子. 思路 考虑在 SAM 上 dp,定义 \(dp_i\) 表示从 \(i\) 节点走到 NULL 节点所花费的最少步数. ...
- 普通人也能轻松掌握的20个DeepSeek高频提示词(2025版)
一.基础原则 1️⃣ 说人话最重要 "不用专业术语,就像和朋友聊天一样描述需求". ️ 错误示范:"请用SWOT分析法输出新能源汽车行业报告". 正确示范:&q ...
- Qt项目下pro文件设置库路径
问题 正常情况下我们会将工程的路径用一个变量来储存 例如: PROJECT_DIR=/home/$$(USER)/svn/embd_linux/app 然后后面的变量引用这个变量,例如: INCLUD ...
- 《<吕氏春秋> 刘本》
<<吕氏春秋> 刘本>(卷三) 编者 刘昱合 其他版本 <吕氏春秋>(卷一) <吕氏春秋>(卷二) <<吕氏春秋> 全本>(卷三 ...