淘宝MySQL文档整理

2019-12-05  本文已影响0人  BenjaminCool

MySQL · 引擎特性 · InnoDB 事务锁系统简介

MySQL · 引擎特性 · Innodb 锁子系统浅析

MySQL · 引擎分析 · InnoDB行锁分析

行级锁
InnoDB 支持到行级别粒度的并发控制,本小节我们分析下几种常见的行级锁类型,以及在哪些情况下会使用到这些类型的锁。

LOCK_REC_NOT_GAP

锁带上这个 FLAG 时,表示这个锁对象只是单纯的锁在记录上,不会锁记录之前的 GAP。在 RC 隔离级别下一般加的都是该类型的记录锁(但唯一二级索引上的 duplicate key 检查除外,总是加 LOCK_ORDINARY 类型的锁)。

LOCK_GAP

表示只锁住一段范围,不锁记录本身,通常表示两个索引记录之间,或者索引上的第一条记录之前,或者最后一条记录之后的锁。可以理解为一种区间锁,一般在RR隔离级别下会使用到GAP锁。

你可以通过切换到RC隔离级别,或者开启选项innodb_locks_unsafe_for_binlog来避免GAP锁。这时候只有在检查外键约束或者duplicate key检查时才会使用到GAP LOCK。

LOCK_ORDINARY(Next-Key Lock)

也就是所谓的 NEXT-KEY 锁,包含记录本身及记录之前的GAP。当前 MySQL 默认情况下使用RR的隔离级别,而NEXT-KEY LOCK正是为了解决RR隔离级别下的幻读问题。所谓幻读就是一个事务内执行相同的查询,会看到不同的行记录。在RR隔离级别下这是不允许的。

假设索引上有记录1, 4, 5, 8,12 我们执行类似语句:SELECT… WHERE col > 10 FOR UPDATE。如果我们不在(8, 12)之间加上Gap锁,另外一个 Session 就可能向其中插入一条记录,例如9,再执行一次相同的SELECT FOR UPDATE,就会看到新插入的记录。

这也是为什么插入一条记录时,需要判断下一条记录上是否加锁了。

不同场景,不同隔离级别下的加锁行为都有所不同,例如在RC隔离级别下,不符合WHERE条件的扫描到的记录,会被立刻释放掉,但RR级别则会持续到事务结束。你可以通过GDB,断点函数lock_rec_lock来查看某条SQL如何执行加锁操作。

上一篇下一篇

猜你喜欢

热点阅读