封锁粒度
一般有两种封锁粒度:行级锁以及表级锁。应该尽量只锁定需要修改的那部分数据,而不是所有的资源。锁定的数据量越少,发生锁争用的可能就越小,系统的并发程度就越高。
读写锁
- 排它锁(Exclusive),简写为 X 锁,又称写锁。
- 共享锁(Shared),简写为 S 锁,又称读锁。
规定:
- 一个事务对数据对象 A 加了 X 锁,就可以对 A 进行读取和更新。加锁期间其它事务不能对 A 加任何锁。
- 一个事务对数据对象 A 加了 S 锁,可以对 A 进行读取操作,但是不能进行更新操作。加锁期间其它事务能对 A 加 S 锁,但是不能加 X 锁。
兼容关系
- | X | S |
---|---|---|
X | × | × |
S | × | √ |
意向锁
使用意向锁(Intention Locks)可以更容易地支持多粒度封锁。意向锁是一种不与行级锁冲突表级锁。
规定:
- 一个事务在获得某个数据行对象的 S 锁之前,必须先获得表的 IS 锁或者更强的锁;
- 一个事务在获得某个数据行对象的 X 锁之前,必须先获得表的 IX 锁。
兼容关系(特别说明,以下是表锁直接的兼容关系)
- | X | IX | S | IS |
---|---|---|---|---|
X | × | × | × | × |
IX | × | √ | × | √ |
S | × | × | √ | √ |
IS | × | √ | √ | √ |
说明:
- 意向锁不会与行级的共享 / 排他锁互斥。IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突。
举例
用户表user:
id | name |
---|---|
1 | zhangsan |
2 | lisi |
3 | wangwu |
事务A,更新id为2的用户名
获取user表上的IX锁;
获取id=2数据行的X锁。
事务B,查询user表
检查到user表上用IX锁;
事务B加锁请求阻塞。
事务C,更新id为1的用户名
获取user表的IX锁;
检测到user表有IX锁;
意向锁不排斥,故事务C获得IX锁;
id=1不存在其他行级锁,获取行级X锁。
说明:若无意向锁,则对于事务B,将要查询表中的行来确定是否存在其他行级锁。