MySQL锁的类型
这里讲到的MySQL锁和锁的类型都是基于InnoDB来说的。并发
共享锁和排他锁
共享锁(shared lock,简称S)容许多个读操做同时进行不相互影响,排他锁(exclusive lock,简称X)会阻塞其它排他锁请求,直到当前释放了锁。优化
意向锁
意向锁是InnoDB为了支持多个粒度上的锁定提出的概念,可让行级锁和表级锁共存。spa
意向锁分为两种,一种是意向共享锁(intension shared lock,简称IS),一种是意向排他锁(intension exclusive lock,简称IX):3d
IS表示一个事务要在这个表加S行锁
IX表示一个事务要在这个表加X行锁
好比select ... lock in share lock会加IS锁,select ... for update会加IX锁。code
在一个事务获取一张表S行锁以前,必须对这张表加IS锁或更高强度的锁,在一个事务获取一张表X行锁以前,必须对这张表加IX锁,表级别的锁互斥关系以下所示:blog
结合下面例子理解互斥关系:索引
在上面例子里,现开启一个事务加了S行锁,而后对表加X锁,会发现对表加X锁被阻塞了,结合上面表,能够分析在加S行锁的时候,给这张表加了一个IS表锁,这样在加X表锁的时候,由于X表锁和IS表锁是互斥的,就致使加X表锁的操做被阻塞了。事务
总而言之,意向锁的目的就是为了加行锁的时候,在表锁维度有个标识,表示当前表正在进行一些操做,在加真正的表锁的时候,就能够识别这个标识,判断要加的表锁是否可以加上。it
记录锁
记录锁又称为行锁,是InnoDB专门提供的一种锁,上面例子里,select * from MyBooks where id = 0 lock in share mode就会加上一个行锁。io
行锁会在增、删、改操做里自动加上,在查询操做,能够显示加上lock in share mode或for update加上。
行锁只会对索引行生效,有几个点须要注意一下:
命中的索引必须是主键或者惟一键索引
若是SQL语句没有使用索引或者优化器决定不用索引,那么就会锁全表
间隙锁
间隙锁是对索引记录之间、第一个索引记录以前或者最后一个索引记录以后的锁定,不管这个范围内有没有这个值,都会被锁定,间隙可能跨过单个索引值、多个索引值甚至为空。
间隙锁有几个须要注意的点:
若是一个条件命中惟一索引,不会使用间隙锁
若是明确只查询一条数据,可是没有命中惟一索引,会使用间隙锁锁定该条索引键以前和以后的间隙
间隙锁的目的是不让在这个间隙里插入数据,间隙锁之间是不排他的,也就是说能够对同一个间隙加多个间隙锁
间隙锁在读提交级别下不生效
假若有表test,有两个字端,字段id是惟一键索引,字段num是普通索引,有数据:
当事务A对3进行加锁时,事务B插入(7, 2),(7, 4)会失败,由于间隙锁把num索引(1, 3),(3, 5)间隙锁住了,这时插入(7, 6)是会成功的。
插入(7, 2)是指插入id=7,num=2。
临键锁
临键锁是记录锁和间隙锁的结合,若是等值条件查询命中非主键索引和非惟一键索引,那么就会命中临键锁,这是会所这条索引键以前和以后的间隙,同时会锁这条索引键。
在上面的例子下,事务B插入(8, 3)会被阻塞。
插入意图锁
插入意图锁的做用是提升插入操做的并发。若是有多个事务的插入操做等待一段间隙被释放,会在等待排他锁时加上插入意图锁,等到间隙锁被释放时,这多个插入操做不会相互阻塞。
自增锁
自增锁是个表级别的锁,专门处理插入操做自增列,一个事务在执行插入操做时,别的事务的插入操做会阻塞,知道这个插入操做执行完毕,这样这个插入操做的自增列的数据是连续的。