表锁
就是在数据表层面加锁。分别是有读锁和写锁。很好理解,读读兼容,写写,读写互斥。加锁的方式和释放方式如下。
lock table user write;
lock table user read;
unlock tables;
行锁
innodb可以给行加锁,相比表锁,这样可以减少加锁的粒度,减少锁的冲突,提高并发能力。行锁有以下两种。
-
共享锁(shared lock):允许事务读行,使用共享锁后,其他事务可以获取相同数据集的共享锁,但是不能获得排他锁。手动加锁方式
select * from table lock in share mode
-
排他锁(exclusive lock):允许事务写行,使用排他锁后,其他事务不能获取相同数据集的共享锁和排他锁。手动加锁方式
select * from table for update
需要知道的是 sql 当中的 insert update delete 会自动获取排他锁,select 不会获取任何锁。
意向锁
- 意向共享锁(intention shared lock):事务要获取共享锁之前要先取得该表的意向共享锁
- 意向排他锁(intention exclusive lock):事务要获取排他锁之前要先取得该表的意向排他锁
因为同时具有表锁和行锁,有些情况下会存在两种锁的冲突。例如:
- 事务a获取了数据行id=1的排他锁,那么其他事务不能够对a进行写操作。
- 事务b此时要对表进行加写锁,肯定是不能让事务b成功的。因为如果成功,b可以对表中任何行进行写操作,那么和数据行id=1的排他锁冲突。
- 此时b加写锁需要判断表是否已经加锁,或者每行是否加排他锁。因此引进意向锁。
- 在b加写锁时,直接判断该表是否已经有意向排他锁即可。
各类锁的兼容性如下:
下图为网络上的图,解释各种锁之间的兼容性。其中 X S为表锁。
注意:意向锁和行锁是不会冲突的
需要注意的是 IS IS, IX IX, IS IX是兼容的,因为排他锁和共享锁是行锁,会针对不同行加锁,所以意向锁可以重复获得。