mysql的并发处理机制_下篇
1 Innodb的锁
类型 | 说明 | 场景 |
S | 共享锁 | 针对于RS隔离级别的查询或者添加Lock in share mode的SELECT查询而产生的锁 |
X | 排它锁 | 针对于update、delete、insert操作而产生的锁 |
IS | 意向共享锁 | 表级别的锁,在添加S锁之前对表格添加IS锁 |
IX | 意向排他锁 | 表级别的锁,在添加X锁之前对表格添加IX锁 |
1.1 锁定兼容情况
- 锁粒度小于表级别的锁的兼容情况
- 对于这两行锁的兼容说明如下:
- 假设有一行数据,添加了行锁S锁,那么这个行数据,可以提供给其他事务进行S锁的申请和添加,但是不支持其他事务对这一行进行X锁的申请和添加。比如,事务A,对 pk100 这一行进行了 查询操作并添加了S锁,那么其他事务仍然可以对这一行数据进行查询,但是不能对这行数据进行 UPDATE 跟 DELETE 操作,会处于锁等待情况,直到该事务A结束并释放S锁;
- 假设有一行数据,添加了X锁,那么这个行数据,不允许其他事务对这一行数据进行加锁。比如,事务A,对pk100这一行进行了UPDATE操作,那么其他事务在事务A没有结束之前,都无法对这一行数据申请 S锁。
- 表级的锁兼容情况
- 对于表级别的锁兼容性如下:
- 当一个表格持有S表锁时,不需要其他事务对该表格申请X锁跟IX锁,但是允许申请S跟IS锁。比如,事务A对表格tba全表读,加了S表锁,期间支持其他事务对tba全表读(申请S表锁成功)、支持其他事务对tba行数据查询(申请IS表锁成功),但是不支持对表格全表的修改操作(申请X表锁等待)跟不支持对表格行数据修改操作(申请IX表锁等待);
- 当一个表格持有X表锁时,持有锁期间,不支持其他所有锁的申请;
- 当一个表格持有IS表锁时,允许申请 S表锁、IS表锁、IX表锁,但是不支持X表锁申请。
- 比如,事务A对表格tba 查询了 id = 10(id为主键)这一行数据,这个时候,表格tba持有IS表锁,id = 10 这一行持有 S 行锁,期间,支持其他事务对 tba 全表查询(申请表锁S成功)或者 基于索引查找(申请表锁IS成功)
- 如果需要对行 id = 20 进行数据修改,则会先申请 tba 的表锁 IX(申请成功),然后再申请id=20行锁X (申请成功);如果需要对 id = 10 这一行数据进行修改,则会申请 tba的表锁 IX(表锁申请成功),然后申请 id = 10 的行锁X(申请堵塞,因为 id = 10 正持有S锁);
- 如果需要对表格进行全表修改,需要申请表锁(X锁),这个时候,IS锁的优势来了,当查看表格是否有其他事务在访问操作时,一看表锁IS就知道有其他事务对表格内部某些数据持有S锁,并且还没有释放,那么这个时候,申请X锁就会处于等待状态,而不需要一行一行去查询每一行数据有没有被其他事务持有锁,可以大规模的减少查询 锁申请情况;
- 当一个表格持有IX表锁时,支持申请IS、IX表锁,但是不兼容S、X表锁。
- 比如,事务A对表格 tba 中 id=10 (id为主键)进行进行 数据修改,这个时候,会对表格 tba 先申请一个 IX 表锁(申请成功),然后申请 id =10 的 X 行锁,申请成功,则 事务A 持有 IX 表锁、id=10的X 行锁,此时事务B 查询 id=20的行,申请表锁 IS 成功,申请 id=20的 S 行锁成功;事务C 修改 id=30的行数据,申请表锁 IX 成功,申请 id=30的行锁 X成功;但是,事务D中,对整个表格发起update或者全表SELECT操作,需要申请 X表锁或者S表锁,正常情况下,应该要对表格的每一行数据进行查看,确保每一行数据的行锁情况,但是因为有了意向锁,事务D一看到 tba 持有 了IX锁,则明白,tba 中某些行持有X锁,则会不兼容其他事务对tba 表锁S ,表锁X的申请。
- 为什么要引入意向表锁?
- 在没有意向锁的时候,如果事务T 需要给表格 A 添加 一个S 表锁,那么就意味这这个表格内部的每一行数据,都不能有X锁,才能够申请 S 表锁成功,如果表格数据很多,一行行查找非常浪费加锁时间,这个时候,就出现了表格意向锁,当表格内部某些行发生 UPATE DELETE INSERT操作,则会对表格 加上 一个意向 IX 表锁,这样 事务T在申请 表格A的 S 表锁时,只需要检查 表格 A 是否有 IX表锁,如果有,则意味内部有 部分行数据持有X锁,则直接进入等待情况,如果表格没有 IX表锁,则直接申请S表锁成功,这是一个多么节约加锁时间的操作!
1.2 锁的级别
- Table Lock
- 表锁,如果没有where条件、无可用索引或者获取的行记录过多,则会使用 table full scan,添加表锁
- Record Lock
- 记录锁,如果执行计划使用了索引,则会根据索引的查找情况添加行锁
- Gap Lock
- 在RR、RS隔离级别,发生在索引值之间,在连续的两个索引值之间添加锁,加锁后,这两个索引值之间,无法插入新的索引值,不包含行记录
- Next-Key Lock
- Record Lock 跟Gap Lock的组合,合体成为Next-KEY Lock
1.3 锁与隔离级别(不考虑 lock in shar mode跟for update )
- RU,读未提交记录,不加锁读,正常写锁;
- RC,快照读,无锁;当前读,加 Record Lock
- RR,快照读,无锁;当前读,对读取到的记录加 Record Lock,同时为了确保where条件范围内的数据无变化,会增加Next key lock
- RS,读写均为当前读,不支持快照读。包括select 在内,对读取到的记录加 Record Lock,同时为了确保where条件范围内的数据无变化,会增加Next key lock。
2 锁的申请与释放过程
age
|
2
|
4
|
7
|
9
|
21
|
25
|
id
|
1
|
4
|
5
|
2
|
3
|
6
|
id
|
1
|
2
|
3
|
4
|
5
|
6
|
age
|
2
|
9
|
21
|
4
|
7
|
25
|
name
|
null
|
null
|
null
|
null
|
null
|
null
|
2.1 Read Uncommitted
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
读不加锁,读未提交数据
可能有脏读、不可重复读及幻读
|
当前读,根据主键修改数据
tbname 加意向表锁 IX
id=4 加 行锁 X
|
表格的age列无索引,所以update过程中,全表加X锁
支持semi-constent-read,如果有其他update语句修改其他行不堵塞,但是不支持 select ... for update
|
同左
|
tb_index
|
表格的age列有索引,update过程中
tb_index 加 表格意向锁 IX
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
|
||
tb_unique_index
|
同上
|
同上
|
2.2 Read Committed
表格
SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
快照读,不加锁
读取的数据不一定是最新版本,但是事务内的所有查询读取数据都是同一版本的行数据,不存在脏读、不可重复读及幻读的情况
|
当前读,根据主键修改数据
tbname 加意向表锁 IX
id=4 加 行锁 X
|
表格的age列无索引,所以update过程中,全表加X锁
支持semi-constent-read,如果有其他update语句修改其他行不堵塞,但是不支持 select ... for update
|
同左
|
tb_index
|
表格的age列有索引,update过程中
tb_index 加 表格意向锁 IX
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
|
||
tb_unique_index
|
同上
|
同上
|
2.3 Read Repeatable
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
快照读,不加锁
读取的数据不一定是最新版本,但是事务内的所有查询读取数据都是同一版本的行数据,不存在脏读、不可重复读及幻读的情况
|
当前读,根据主键修改数据
tbname 加意向表锁 IX
id=4 加 行锁 X
|
表格的age列无索引,所以update过程中
全表加X锁,期间全表堵塞UPDATE\DELETE\INSERT
|
同左
|
tb_index
|
表格的age列有索引,update过程中
tb_index 加 表格意向锁 IX
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
你以为结束了!并没有,这里有趣了!
还会添加两个gap lock ((9,2) ,(21,3)),((21,3), (21,25))
这里我们单独拎出小表格来分析。
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
同时会在索引 age的值上添加 3个 gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
以为跟上面的加锁范围一样,no no no
唯一索引列上 每一个age都是唯一的,也就是age=21只有一个,不会再INSERT一个新的 age =21进来,故在这里不需要加gap lock,加锁情况如下:
tb_index 加 表格意向锁 IX
age=21 行添加行锁 X
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
同时会在索引 age的值上添加 3个 gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
但是,范围查询添加到gap lock在其他情况下跟非唯一索引会有一些差别,可以看下表的例子。
|
2.3.1 RR下的非唯一索引加锁情况
2.3.2 RR下的唯一索引加锁情况
update tbname set name=...
where age between 1 and 7
|
update tbname set name=...
where age between 2 and 7
|
update tbname set name=...
where age between 5 and 10
|
update tbname set name=...
where age between 15 and 50
|
|
tb_index
|
(-∞,2),(2,4),(4,7),(7,9)
|
(-∞,2),(2,4),(4,7),(7,9)
|
(4,7),(7,9),(9,21)
|
(9,21),(21,25),(25,+∞)
|
tb_unique_index
|
(-∞,2),(2,4),(4,7)
|
(2,4),(4,7)
|
(4,7),(7,9),(9,21)
|
(9,21),(21,25),(25,+∞)
|
2.4 Read Serializable
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
不支持快照读,所有SELECT都是当前读,所有SELECT操作都需要加S锁,除主键定值查找\唯一索引定值查找外,其他基于索引或者主键的范围查找都会添加 S GAP LOCK。并发度是四个隔离级别中性能最差的。
|
当前读,根据主键修改数据
tbname 加意向表锁 IX
id=4 加 行锁 X
|
表格的age列无索引,所以update过程中
全表加X锁,期间全表堵塞UPDATE\DELETE\INSERT
|
同左
|
tb_index
|
表格的age列有索引,update过程中
tb_index 加 表格意向锁 IX
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
在age索引上 添加两个gap lock ((9,2) ,(21,3)),((21,3), (21,25))
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
同时会在索引 age的值上添加 3个 gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
唯一索引列上 每一个age都是唯一的,也就是age=21只有一个,不会再INSERT一个新的 age =21进来,故在这里不需要加gap lock,加锁情况如下:
tb_index 加 表格意向锁 IX
age=21 行添加行锁 X
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
同时会在索引 age的值上添加 3个 gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
但是,范围查询添加到gap lock在其他情况下跟非唯一索引会有一些差别,可以看下表的例子。
|
表格 SQL
|
select * from tbname
where id=5
|
select * from tbname
where id betwee 5 and 15
|
select * from tbname
where age=21
|
select * from tbname
where age betwee 5 and 9
|
tb_no_index
|
主键定值查找
表格tbname 添加 IS 意向锁
id=5 添加 S锁
|
主键范围查找
表格tbname 添加 IS 意向锁
id=5,id=6 两行数据 添加 S锁
同时添加2个 S GAP LOCK ,分别为 ((5,7),(6,25))跟((6,25),+∞)
|
全表查找
表格 tbname 添加 IS 意向锁
由于全表查找,整个表格 再次添加 S 表锁
|
全表查找
表格 tbname 添加 IS 意向锁
由于全表查找,整个表格 再次添加S 表锁
|
tb_index
|
ix_age索引查找
表格tbname 添加 IS 意向锁
索引上 age = 21 添加 S 行锁
主键上 id=3 添加 S 行锁
同时添加 2个 S GAP LOCK ,分别为 ((9,2) ,(21,3)),((21,3), (21,25))
|
ix_age索引查找
表格tbname 添加 IS 意向锁
age索引上面,age=7,age=9 行添加行锁 S
再在主键上,给id=2,id=5 这一行数据,添加行数 S
同时会在索引 age的值上添加 3个 S gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
ix_age索引查找
表格tbname 添加 IS 意向锁
索引上 age = 21 添加 S 行锁
主键上 id=3 添加 S 行锁
由于age列唯一,故不需要添加GAP LOCK
|
ix_age索引查找
表格tbname 添加 IS 意向锁
age索引上面,age=7,age=9 行添加行锁 S
再在主键上,给id=2,id=5 这一行数据,添加行数 S
同时会在索引 age的值上添加 2 个 S gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))
|
3 SQL分析
3.1 支持ICP情况
3.2 不支持ICP情况
mysql的并发处理机制_下篇的更多相关文章
- mysql的并发处理机制_上篇
回来写博客,少年前端时间被django迷了心魄 如果转载,请注明博文来源: www.cnblogs.com/xinysu/ ,版权归 博客园 苏家小萝卜 所 ...
- 说一说MySQL的锁机制
锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则. 最显著的特点是不同的存储引擎支持不同的锁机制,InnoDB支持行锁和表锁,MyISAM支持表锁. 表锁就是把 ...
- 关于MySQL的锁机制详解
锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则. 最显著的特点是不同的存储引擎支持不同的锁机制,InnoDB支持行锁和表锁,MyISAM支持表锁. 表锁就是把 ...
- mysql的Replication机制
mysql的Replication机制 参考文档:http://www.doc88.com/p-186638485596.html Mysql的 Replication 是一个异步的复制过程. 从上图 ...
- MySQL- 锁机制及MyISAM表锁
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许 多用户 共享的资源.如何保证数据并发访问的一致性.有效性是所 ...
- MysqL自动提交机制的关闭
MysqL在执行一句数据库操作命令的时候,通常都是自动提交的.常用引擎下有两种,分别是MyIsam和InnoDB,MyIsam是不支持事务处理的,但InnoDB支持,但InnoDB在不开启事务处理的情 ...
- MySQL的安全机制
MySQL的安全机制: 1.MySQL登录 mysql -u账户 -p密码 -h127.0.0.1 -P端口 数据库名 mysql -h hostname|hostIP -p port -u user ...
- MySQL的复制机制
MySQL的复制机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MySQL复制介绍 1>.MySQL复制允许将主实例(master)上的数据同步到一个或多个从实例( ...
- MySQL中间件方案盘点_搜狐科技_搜狐网
MySQL中间件方案盘点_搜狐科技_搜狐网
随机推荐
- Java-Properties用法-入门
对于应用程序的配置,通常的做法是将其保存在独立的配置文件中,程序启动时加载,修改时保存.Java中Properties类就提供了这样一种机制,配置项以Key-Value的数据结构存储在文本文件中,扩展 ...
- 201521123100《Java程序设计》 第10周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. A: 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结 ...
- Lucene第二篇【抽取工具类、索引库优化、分词器、高亮、摘要、排序、多条件搜索】
对Lucene代码优化 我们再次看回我们上一篇快速入门写过的代码,我来截取一些有代表性的: 以下代码在把数据填充到索引库,和从索引库查询数据的时候,都出现了.是重复代码! Directory dire ...
- could not get next sequence value
1.触发事件 在电脑A上敲项目代码,数据库原始资料是直接使用别人写好的sql导入(建表和导入表数据等): 将电脑A上数据库的资料,使用PL/SQL Developer导出项目中所用表(此时未导出Ora ...
- Tomcat代码执行漏洞(CVE-2017-12615)的演绎及个人bypass
0x00 漏洞简介 2017年9月19日,Apache Tomcat官方确认并修复了两个高危漏洞. 漏洞CVE编号:CVE-2017-12615和CVE-2017-12616. 其中 远程代码执行漏洞 ...
- 与 Hadoop 对比,如何看待 Spark 技术?
主要是先看MapReduce模型有什么问题? 第一:需要写很多底层的代码不够高效,第二:所有的事情必须要转化成两个操作Map/Reduce,这本身就很奇怪,也不能解决所有的情况. 其实Spark出现就 ...
- Spring+SpringMVC+MyBatis整合进阶篇(四)RESTful实战(前端代码修改)
前言 前文<RESTful API实战笔记(接口设计及Java后端实现)>中介绍了RESTful中后端开发的实现,主要是接口地址修改和返回数据的格式及规范的修改,本文则简单介绍一下,RES ...
- 11 Linear Models for Classification
一.二元分类的线性模型 线性分类.线性回归.逻辑回归 可视化这三个线性模型的代价函数 SQR.SCE的值都是大于等于0/1的 理论分析上界 将回归应用于分类 线性回归后的参数值常用于pla/pa/lo ...
- 使用千位分隔符(逗号)表示web网页中的大数字
做手机端页面我们常常遇到数字,而在Safari浏览器下这些数字会默认显示电话号码,于是我们就用到了补坑的方法加入<meta>标签: <meta name="format-d ...
- CentOS7 + Nginx1.13.5 + PHP7.1.10 + MySQL5.7.19 源码编译安装
一.安装Nginx 1.安装依赖扩展 # yum -y install wget openssl* gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng ...