Mysql Innodb 锁机制
latch与lock
latch 可以认为是应用程序中的锁,可以称为闩锁(轻量级的锁) 因为其要求锁定的时间必须要非常短,若持续时间长,则会导致应用性能非常差,在InnoDB存储引擎中,latch又可以分为mutex(互斥锁)和rwlock(读写锁),其目的用来保证并发线程操作临界资源的正确性,并且没有死锁检测的机制
在InnoDB存储引擎中的latch,可以通过命令SHOW ENGINE INNODB MUTEX 来进行查看
mysql > SHOW ENGINE INNODB MUTEX;
lock可以认为是数据库提供的锁,用来锁定的是数据库中的数据。并且一般lock对象仅在事务commit或rollback后进行释放(不同事务隔离级别释放的时间可能不同),lock是有死锁机制的。
在InnoDB存储引擎中的lock 可以通过show engine innodb status,information_schema.INNODB_LOCKS,INNODB_TRX,INNODB_LOCK_WATIS信息来查看
线程获取lock的流程:
在对数据加lock的时候会先对数据所在的页面添加latch,然后再对数据添加lock,添加完lock后再释放页面的Latch。
这种机制主要是为了保证线程获取的行数据的一致性和完整性.
如果lock被其他的线程占有,线程先释放页面latch,等待lock,待获取lock后会再次对页面添加latch,查看页面数据是否有改动,然后尝试再次获取对应的lock
共享锁与排他锁
innodb储存引擎提供了如下两种标准的行级锁
共享锁(S) 允许一个事务去读一行
排他锁(X) 允许获得排他锁的事务更新或删除数据
同时innodb储存引擎支持多粒度锁定,为了支持在不同的粒度上进行加锁操作,innodb支持另一种额外的锁方式,称之为意向锁
意向共享锁(IS) 事务想要获得一张表中某几行的共享锁
意向排他锁(IX)事务想要获得一张表中某几行的排他锁
在行锁的实现上
mysql提供了三种的行锁的算法
分别是
Record Lock 记录锁,单个记录上的锁
Gap Lock 间隙锁,锁定一个范围,但不包含记录本身
Next-key Lock Gap Lock + Record Lock 锁定一个范围,并且锁定记录本身
Mysql是如何加锁的
非特殊注明 默认在RR隔离级别下进行讨论
InnoDb的行锁是对索引加锁的,对扫描的行边扫描边加锁,如果走的是二级索引(非聚簇索引)除了需要对二级索引加锁外,还需要根据二级索引里面的主键信息扫描主键的聚簇索引,对主键加锁,
加锁的数据行数会受到Mysql是否支持Index Condition PushDown而影响(Mysql 5.6支持ICP),加锁的数量可能远远大于满足条件的记录数量
这里需要加两次锁的原因是
如果
语句A 使用二级索引对记录X进行更新操作,
语句B使用聚簇索引对记录X进行更新操作,
如果A仅对二级索引进行加锁,那么并发的语句B将感受不到语句A的存在,违背了同一条记录上的更新/删除必须串行执行的约束
select * from table where?
RC级别下 : 无需加锁,一致性非锁定读,使用快照读,读取被锁定行的最新一份数据,因此会出现前后读取数据不一致的情况
RR级别下:无需加锁,一致性非锁定读,使用快照读,读取事务开始时的行数据版本,因此前后读到的数据是一样的
Serializable级别下:使用当前读,需要加锁,innodb内部将select语句转换为了select … lock in share mode
insert?
insert会对插入成功的行加上记录锁,不会阻止其他并发的事务往这条记录之前插入记录。在插入之前,会先在插入记录所在的间隙加上一个插入意向意向锁(并发的事务可以对同一个间隙加插入意向锁锁)。如果insert 的事务出现了duplicate-key error ,事务会对duplicate index record的记录加共享锁。这个共享锁在并发的情况下是会产生死锁的,比如有两个并发的insert都对要对同一条记录加共享锁,而此时这条记录又被其他事务加上了排它锁,排它锁的事务将这条记录删除后,两个并发的insert操作会发生死锁。
delete?
delete操作仅是将主键列中对对应的记录delete flag设置为1,记录并没有被删除,还是存在于B+树中
真正的删除操作被延迟了,最终在purge操作中完成
延迟到purge操作的原因是的innodb支持mvcc多版本控制,所以记录不能在事务提交时立即进行删除,只有当对应的行记录不被任何其他事务引用的时候,才可以由purge进行真正的删除
delete操作过程中:
找到满足条件的记录,并且记录有效,则对记录加X锁
找到满足条件的记录,但是记录无效(标识为删除),则对记录加next key锁、;
未找到满足条件的记录,则对第一个不满足条件的记录加Gap锁,保证没有满足条件的记录插入;
update?
对满足条件的记录next-key锁,如果是等值匹配并且使用唯一索引或是聚簇索引,那么可以只添加记录锁
唯一索引中含NULL值的记录,将不会添加记录锁,转而为next-key锁 因为NULL不等于NULL,NULL和任何值比较均返回NULL,包括NULL本身,但是 NULL is NULL
死锁案例分析
create table `deadlocktest`
(
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`a` bigint(20) unsigned NOT NULL,
`b` bigint(20) unsigned NOT NULL,
`c` bigint(20) unsigned NOT NULL,
`d` bigint(20) unsigned NOT NULL,
`e` bigint(20) unsigned NOT NULL,
PRIMARY KEY(`id`),
UNIQUE KEY `I_a`(`a`),
KEY `I_b` (`b`),
KEY `I_c` (`c`)
)ENGINE=InnoDb ;
insert into deadlocktest (a,b,c,d,e)values(1,999,3,4,5);
insert into deadlocktest (a,b,c,d,e)values(2,998,4,5,6);
insert into deadlocktest (a,b,c,d,e)values(3,997,4,5,6);
insert into deadlocktest (a,b,c,d,e)values(4,996,3,4,5);
...
insert into deadlocktest (a,b,c,d,e)values(1000,1,3,4,5);
3个insert的死锁
事务A |
事务B |
事务C |
begin; |
begin; |
begin; |
insert into deadlocktest (a,b,c,d,e)values(4,996,3,4,5); |
||
insert into deadlocktest (a,b,c,d,e)values(4,996,3,4,5); |
||
insert into deadlocktest (a,b,c,d,e)values(4,996,3,4,5); |
||
rollback; |
||
1 row affected |
Deadlock found when trying to get lock; try restarting transaction |
事务A 获得排他锁,插入数据成功
事务B 事务C,因为记录duplicate-key error转而持有行的共享锁
事务A回滚,释放了持有的排他锁,事务B和事务C需要获得该行的排他锁,但是由于互相都持有对应行的共享锁,互相等待,造成死锁
2个update的死锁
事务A |
事务B |
begin; |
begin; |
update deadlocktest force index(I_b) set e = sleep(5) where b>0; |
|
update deadlocktest force index(I_c) set e = sleep(5) where c>2; |
|
Deadlock found when trying to get lock; try restarting transaction |
Rows matched: 4 Changed: 4 Warnings: 0 |
两个update事务,加锁顺序不一样导致的死锁
InnoDb的行锁是对索引加锁的,对扫描的行边扫描边加锁,如果走的是二级索引(非聚簇索引)除了需要对二级索引加锁外,还需要根据二级索引里面的主键信息扫描主键的聚簇索引,对主键加锁
3个以上delete的死锁
事务A |
事务B |
事务B |
begin; |
begin; |
begin |
delete from deadlocktest where a=550 |
||
delete from deadlocktest where a=550 |
||
delete from deadlocktest where a=550 |
||
commit; | 0 rows affected | Deadlock found when trying to get lock; try restarting transaction |
delete操作仅是将主键列中对对应的记录delete flag设置为1,实际的删除延迟到purge中
delete删除时如果找到满足条件的记录,但是记录无效(标识为删除),则对记录加next key锁、;
死锁日志
3个delete的死锁比较难以复现,我是利用如下脚本完成的
MY_DB="mysql -hxxx -Pxxx -uxxx -pxxx"
while :
do
echo "use test;begin; delete from deadlocktest where a=499;rollback;" | $MY_DB
done
该类delete死锁的出现条件
1、针对唯一索引上等值查询的删除
2、有3个以上并发删除操作
3、事务的隔离级别是RR
4、INNODB储存引擎
参考文献
https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html
http://hedengcheng.com/?p=771#_Toc374698320
Mysql Innodb 锁机制的更多相关文章
- MySQL InnoDB锁机制
概述: 锁机制在程序中是最常用的机制之一,当一个程序需要多线程并行访问同一资源时,为了避免一致性问题,通常采用锁机制来处理.在数据库的操作中也有相同的问题,当两个线程同时对一条数据进行操作,为了保证数 ...
- MySQL InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析
MySQL InnoDB支持三种行锁定方式: l 行锁(Record Lock):锁直接加在索引记录上面,锁住的是key. l 间隙锁(Gap Lock):锁定索引记录间隙,确保索引记录的间隙 ...
- MySQL- InnoDB锁机制
InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题.下面我们先介绍一点背景知识 ...
- MySQL的innoDB锁机制以及死锁处理
MySQL的nnoDB锁机制 InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,innodb正常的select ...
- InnoDB锁机制分析
InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工作机制.通过 ...
- [转载] 数据库分析手记 —— InnoDB锁机制分析
作者:倪煜 InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工 ...
- MySQL- 锁机制及MyISAM表锁
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许 多用户 共享的资源.如何保证数据并发访问的一致性.有效性是所 ...
- mysql insert锁机制【转】
最近再找一些MySQL锁表原因,整理出来一部分sql语句会锁表的,方便查阅,整理的不是很全,都是工作中碰到的,会持续更新 笔者能力有限,如果有不正确的,或者不到位的地方,还请大家指出来,方便你我,方便 ...
- 说一说MySQL的锁机制
锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则. 最显著的特点是不同的存储引擎支持不同的锁机制,InnoDB支持行锁和表锁,MyISAM支持表锁. 表锁就是把 ...
随机推荐
- 如何迭代输出某文件夹下的所有文件的路径?(os.walk用法)
查看目录结构: tree 查看文件结构: os.walk 查看os.walk用法: help(os.walk) For each directory in the directory tree roo ...
- 支付宝pc网页支付
本文讲解如何在pc网页上完成支付宝的支付功能, 详细讲解了支付宝的配置信息,项目如何使用配置信息等, 本项目中代码可以直接运行, 也可以将代码迁移至你自己的项目中直接使用. 注意: 下面讲解的功能只能 ...
- IO流与IO缓冲
1.字节与字符的演变 public class inputStream { public static void test1() throws Exception{ File file= new Fi ...
- mvc中传入字典的模型项的类型问题
刚项目一直报这个错,找了一会发现忘了给他模型项了,我把这个小问题纪录下来,希望你们别犯这个小错
- 循序渐进之Spring AOP(2) - 基本概念
学习AOP前要先了解几个重要术语:Joinpoint.Pointcut.Advice 仍然以改装车比喻,拿到心爱的汽车后想做改装,第一件事是什么?找到要改装的地方.车上可改装的地方很多,但每个人感兴趣 ...
- POJ 1741 Tree(树的点分治,入门题)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21357 Accepted: 7006 Description ...
- [ZOJ3213] Beautiful Meadow
插头DP...网格图,有障碍,格子上有权值,求总权值最大的简单路径. 因为路径的起始点不确定..所以多开一维表示当前已经有多少个独立插头.. 只要不合并相同的联通块,并且已经用了2个独立插头,那就是一 ...
- [bzoj1997][Hnoi2010]Planar(2-sat||括号序列)
开始填连通分量的大坑了= = 然后平面图有个性质m<=3*n-6..... 由平面图的欧拉定理n-m+r=2(r为平面图的面的个数),在极大平面图的情况可以代入得到m=3*n-6. 网上的证明( ...
- PL/SQL 实现行列转换
这篇博文写的是简单的行列转换的,以一个具体的例子来给出. 以前在论坛上有人问过相关的问题,上面的回答五光十色,有很多是可行的,当然更多的是自以为很高端,实际却不着边际的回答.下面进入正题. part1 ...
- c#版 K线控件(Stock)
K线起源于日本米市交易,它的基本用途就是为了寻找"买卖点".股市及期货市场中的K线图的画法包含四个数据,即开盘价.最高价.最低价.收盘价,所有的k线都是围绕这四个数据展开,反映大势 ...