行级锁

InnoDB引擎特有的

记录锁

锁住某行记录,分为读写锁,事务提交后自动释放,例如select * from table_name where id = 1 for update;就给id=1这行记录上了写锁

间隙锁

锁住行与行之间的间隙,防止其它事务在间隙中插入数据,产生幻读,间隙锁是不互斥的(如果涉及到记录锁或者临键锁,还是会互斥阻塞),两个事务可以拥有同一段间隙的间隙锁,但要插入数据时发现这段间隙被其它事务锁上了就插不了了。间隙锁是为了解决幻读,防止其它事务在区间内插入数据

临键锁(间隙+记录锁)

加临键锁的时候是先加间隙锁,后加记录锁,这就有可能出现加间隙锁能成功,加记录锁被阻塞,然后间隙锁与其它事务发生死锁

前开后闭区间,锁住某行以及这一行之前的间隙,如(1, 3],锁住3这一行和1到3行之间的间隙,因为有记录锁,会产生读写互斥,间隙锁之间不互斥

插入意向锁

插入意向锁是一个间隙锁,但这个间隙锁实际上锁住的不是一个区间,而是区间中插入的那个点,所以算是一种特殊的间隙锁,插入意向锁和插入意向锁会互斥,即两个事务可以在同一个区间插入,但不能在同一个区间上相同的点插入;插入意向锁与间隙锁互斥,即插入的点所处的区间不能被其它事务的间隙锁锁住

当事务要插入记录时,判断是否有与插入意向锁冲突的锁,如果有,加插入意向锁,进入锁等待,如果没有,什么锁都不加,直接插入数据,就是说不加插入意向锁!

插入完成后,会给插入的这个数据上个记录锁(其实不会上记录锁,这是个隐式锁,后面会介绍),防止其它事务更改这条数据,直到事务提交后释放这个记录锁

当间隙中存在间隙锁,与插入意向锁冲突

当间隙中存在插入意向锁,间隙锁阻塞

当间隙中存在插入意向锁,但要插入的点和自己不同时,不阻塞(插入意向锁是在间隙中锁住某个点)