1. Shared and Exclusive Locks
- Shared Lock(简称S Lock,共享锁): 允许持有锁的事务读取行的操作
- Exclusive Lock(简称 X Lock,排他锁): 允许持有锁的事务进行更新和删除行的操作
事务T1如果持有记录a的S Lock,此时事务t2也对记录a进行操作时,有两种情况:
- t2请求的是S Lock: t1,t2同时持有记录a的S Lock
- t2请求的是X Lock: t2会等待t1释放锁后,才能获取X Lock
事务t1如果持有是记录a的X Lock,那么t2不管请求S 还是X Lock,都要等t1释放锁后才能去请求。
2. Intention Locks
Intention Locks是表级锁,它表示之后的事务需要获取哪种类型的行锁(S、X)。
- Intention Shared Lock(IS Lock): 表示事务意图在表中各个行上加一个共享锁
- Intention Exclusive Lock (IX Lock): 表示事务意图在表中各个行上加一个排他锁
我们可以通过SELECT ... FOR SHARE
和 SELECT ... FOR UPDATE
来获取IS、IX Lock。
意图锁有以下限制:
- 在事务可以获取表中某行的共享锁之前,它必须首先获取表上的IS锁或更强的锁(IX、S、X)。
- 在事务可以获取表中某行的独占锁之前,它必须首先获取表上的IX锁。
表级锁的兼容性如下表:
\ | X | IX | S | IS |
---|---|---|---|---|
X | Conflict | Conflict | Conflict | Conflict |
IX | Conflict | Compatible | Conflict | Compatible |
S | Conflict | Conflict | Compatible | Compatible |
IS | Conflict | Compatible | Compatible | Compatible |
如果事务请求的锁和先有锁兼容,则获取到锁。否则,事务会等待,直到现有的锁被释放。
2.1 SELECT … FOR UPDATE
T1:
1 | mysql> start transaction; |
表里就两条记录,但有三把行锁 ?
此时事务T2
1 | mysql> start transaction; |
3. Record Locks
Record Lock锁的是索引。如果表没有,InnoDB会建一个隐藏的聚簇索引,并用该隐藏索引来锁定记录。
1 | mysql> start transaction; |
4. Gap Locks
T1开启一个事务 并执行下面语句
1 | mysql> start transaction; |
T2
1 | mysql> start transaction; |
当where xxx=?
条件的xxx
不是索引或者非唯一索引,会锁住前一个间隙
1 | mysql> start transaction; |
T2开启一个事务,并执行下面insert
语句,
1 | mysql> start transaction; |
上面的情况锁住的区间是[12,15]
检索条件必须有索引,没有索引的话,会锁定整张表所有的记录
T1
1 | mysql> start transaction; |
T2
1 | mysql> start transaction; |
1 | MySQL thread id 20, OS thread handle 13996, query id 834 localhost ::1 root update |
PS: 如果指定区间[5,10],没有值为5和10的记录。insert 数据的时候,gap locks 会扩大到就近的存在记录的范围。如扩大到[3,15]
5. Insert Intention Locks
不同数据插入到相同索引间隙不需要等待,互不影响。
6. Next-Key Locks
InnoDB在REPEATABLE READ
事务隔离级别下,默认开启。其实就是record lock 和gap lock 组合使用。
官方文档写的范围
1 | 假设索引包含值10,11,13和20, |