共享锁(S) :允许一个事务去读一行,阻止其他事务获得相同的数据集的排他锁。
排他锁(X) :允许获得排他锁的事务更新数据,但是组织其他事务获得相同数据集的共享锁和排他锁。
可以这么理解:
共享锁就是我读的时候,你可以读,但是不能写。排他锁就是我写的时候,你不能读也不能写。其实就是MyISAM的读锁和写锁,但是针对的对象不同了而已。
除此之外InnoDB还有两个表锁:
意向共享锁(IS) :表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁
意向排他锁(IX) :类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。
意向锁是InnoDB自动加的,不需要用户干预。
对于insert、update、delete,InnoDB会自动给涉及的数据加排他锁(X);对于一般的Select语句,InnoDB不会加任何锁,事务可以通过以下语句给显示加共享锁或排他锁。
共享锁:select * from table_name where .....lock in share mode
排他锁:select * from table_name where .....for update
InnoDB行锁是通过给索引项加锁实现的,索引分为主键索引和非主键索引两种,如果 一条 sql语句 *** 作了主键索引,MySQL就会锁定这条主键索引如果一条语句 *** 作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引,如果没有索引,InnoDB会通过隐藏的聚簇索引来对记录加锁。也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。
InnoDB对于行的查询都是采用了Next-Key Lock的算法,锁定的不是单个值,而是一个范围(GAP)。上面索引值有1,3,5,8,11,其记录的GAP的区间如下:是一个 左开右闭 的空间(原因是默认主键的有序自增的特性,结合后面的例子说明)
(-∞,1],(1,3],(3,5],(5,8],(8,11],(11,+∞)
InnoDB对于行的查询都是采用了Next-Key Lock的算法,锁定的不是单个值,而是一个范围,按照这个方法是会和第一次测试结果一样。但是,当查询的索引含有唯一属性的时候,Next-Key Lock 会进行优化,将其降级为Record Lock,即仅锁住索引本身,不是范围。
Next-Key Lock是行锁与间隙锁的组合,这样,当InnoDB扫描索引记录的时候,会首先对选中的索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。如果一个间隙被事务T1加了锁,其它事务是不能在这个间隙插入记录的。
在第一个session中执行
在第二个sessio中执行
在第三个sessio中执行
可以看到二三中都在等在锁释放,这个时候在第一个session中执行
可以在二三中看到有一个
说到底还是意向锁和gap锁导致的,锁的知识另写总结吧,这里避免的话:
1 不用 insert into on duplicate key update
2 非要用insert into on duplicate key update的话,就不用rr隔离级别(没有gap锁)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)