一.Latch和Tlock的关系
Latch:为保护临界资源的正确性而设计,例如保护正在使用的内存页面不被破坏等。
没有死锁检测机制,轻量锁,并且作用对象时内存页面或是内存共享变量.
Tlock:事务锁,作用对象是事务,有死锁检测机制.
在innodb内部,为了减少死锁的发生概率,Latch不会等待Tlock.
线程获取行锁的流程:
在对行加锁的时候会先对行所在的页面添加lath,然后再对行添加Tlock,待对行添加完Tlock后再释放页面的Lath。
这种机制主要是为了保证线程获取的行数据的一致性和完整性.
如果行被其他的线程占有,线程先释放页面latch,等待行锁,待获取行锁后会再次对页面添加latch,查看页面数据是否有改动,再次获取改动后的行。
二.DML加锁规则
DML加锁的语句有,insert/update ... where ..../ delete from .. where .. / select * from
insert不添加锁,但是在有唯一所以的时候,会对唯一索引做唯一性检查(加s锁,在将s锁转化为x锁),都是行锁。
update ... where.. / delete ... where ../select ... where lock in share mode / select .. where .. for update
(1).数据查找走了索引,但是表达式为不等号,则会添加区间锁(gap).
例如. > 10 ,则锁定区间为(10,+~)
<10 ,则锁定区间为(-~,10) .
(2).数据查找走的唯一索引,并且表达式为等号(=),则添加行锁(record lock but not gap) 。
(3).数据查找为非唯一索引,并且表达式为等号,会添加区间锁(record lock gap),会锁定的区间为( ] ,允许更新,不允许插入.
重点:区间锁是为了防止出现幻觉读的,所以只阻塞插入操作.对更新不影响
三.死锁案例分析.
(1).insert,并发插入相同的数据,并且插入字段中有唯一键存在,
在正常的插入过程中是不会添加任何锁的,但是在有唯一键的时候会对唯一键的字段做唯一性检查,在检查的过程中会对记录共享锁(S),
当多个线程对同一行添加共享锁(S)之后,会将共享锁(s)转化为排他锁(X),此时就会相互等待,产生死锁.
(2).update并发更新,更新的字段有索引
线程一根据索引字段更新一个行,线程二根据主键更新索引字段.
此时线程一获得了索引等待行 ,线程二获得了行等待索引。
(3)delete,根据某一个唯一索引字段并发删除记录。
过程非常复杂,详情见一下链接:
http://www.cnblogs.com/sunss/p/3166550.html
(4).insert和delete并发,有非聚集索引
线程1根据某个非聚集索引字段删除数据,线程2插入相同的记录。
线程1获得了索引,等待行,线程2获得了行,等待索引。
(5).insert 和update并发,有非聚集索引。
死锁原理同4.
(6)delete 和update 并发.
原理同2.
死锁案例连接:
innodb next-key lock引发的死锁:
http://www.cnblogs.com/xhan/p/3701459.html
唯一键造成的死锁:
http://www.cnblogs.com/sunss/p/3166550.html
mysql中的delete死锁