diff --git a/mysql/mysql文档/锁.md b/mysql/mysql文档/锁.md index fe85a81..38e0294 100644 --- a/mysql/mysql文档/锁.md +++ b/mysql/mysql文档/锁.md @@ -79,7 +79,7 @@ Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 1: len 6; hex 00000000274f; asc 'O;; 2: len 7; hex b60000019d0110; asc ;; ``` - + ### 一致性读 #### 一致性非锁定读 `一致性非锁定读`是指innodb通过mvcc(多版本并发控制)来读取行数据。如果当前待读取的行正在执行update或delete操作,那么此时`读取行的操作并不会被阻塞,而是会去读取当前被修改行的快照历史版本`。这种行为被成为`非锁定读`。 @@ -121,6 +121,23 @@ Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 并且,`for update`或`lock in share mode`添加的行锁,在事务commit或rollback时会被释放。 + ### Gap Lock + gap lock是针对index record之间的间隙来进行加锁的(或是针对第一条index record之前或最后一条index record之后的间隙进行加锁)。例如,`SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; `语句会阻止其他事务在c1值的`10~20`范围之间插入数据,不管这条数据存不存在,在`10~20`的间隙之前所有的值都被锁定了。 + 间隙范围可能跨单个索引值,多个索引值甚至为空。 + 间隙锁在部分的事务隔离级别中有使用,在其他隔离级别中则不会被使用。 + + 在通过unique index区查询唯一行时,并不需要使用间隙锁(并不包含unique复合索引的情况)。例如,在id为唯一索引的情况下,如下所示的语句只会使用index record lock: + ```sql + SELECT * FROM child WHERE id = 100; + ``` + + 但是,如果id并不是索引,或者id的缩影并不unique,那么上述语句会对之前的间隙进行加锁。 + + 值得注意的是,不同事务针对同一间隙,可以持有相互冲突的锁。例如,A事务针对间隙持有S锁,而B事务针对间隙持有X锁,当index record从索引中被清除时,不同事务所持有的间隙锁将会被合并。 + + 在innodb中,间隙锁只是为了防止其他事务在该间隙中插入锁,间隙锁是可以共存的。如果事务A针对间隙加锁,这并不会阻止事务B获取同一间隙的锁。`间隙的S锁和X锁都遵循该规则,且S锁和X锁之间并不会相互冲突,间隙的S锁和X锁功能相同`。 + + 间隙锁可以被显示的禁用,如果将事务的隔离级别改为`read committed`,在查找和索引扫描时间隙锁将会被禁用,间隙锁只会被用于外键检查和重复key检查。