Lock
InnoDB 锁算法¶
记录锁(Record Lock) | 锁定单个行记录 |
间隙锁(Gap Lock) | 锁定一个范围不包括记录本身 |
临键锁(Next-Key Lock) | 锁定一个范围包含记录本身 |
InnoDB 锁特性¶
SELECT
操作的不可重复读问题通过 MVCC 解决UPDATE
、DELETE
的不可重复读问题通过 Record Lock 解决INSERT
的不可重复读问题通过 Next-Key Lock 解决
全局锁¶
使用场景¶
- 全局逻辑备份(
mysqldump
)
启动方法¶
-
方法一(FTWRL)
-
方法二
注意事项¶
-
有些系统中
readonly
的值会被用来处理其它逻辑(如判断一个库是主库还是备库) -
如果执行 FTWRL 后由于客户端发生异常断开,MySQL 会自动释放这个全局锁,整个库回到可正常更新状态
-
将库设置未
readonly
后,若客户端发生异常,数据库会一直保持readonly
状态,导致整库长时间处于不可写状态 -
readonly
对Super
权限无效 -
为什么需要 FWTRL?
- 当
mysqldump
使用参数--single-transaction
的时候,导数据之前就会启动一个事务来确保拿到一致性快照视图。而由于 MVCC 的支持,这个过程中数据是可以正常更新的。 - 所以
--single-transaction
方法只适用于所有的表使用事务引擎的库。如果有的表使用了不支持事务的引擎,那么备份就只能通过 FTWRL 方法
- 当
表级锁¶
读写锁¶
-
表共享读锁(共享锁)
-
表独占写锁(排它锁)
元数据锁(MDL)¶
- MDL 的作用是防止 DDL 和 DML 并发的冲突,保证读写的正确性
- 不需要显式的使用 MDL,因为当我们对数据库表进行操作时,会自动给这个表加上 MDL
意向锁(Intention Lock)¶
-
意向锁是表级锁,是 InnoDB 主动加的,不需要手动处理,其目的是为了快速判断表里是否有记录被加锁
- 如果没有意向锁,那么加独占锁时,就需要遍历表里所有记录,查看是否有记录存在独占锁,这样效率会很低
- 如果有了意向锁,在对记录加独占锁前,会先加上表级的意向独占锁,那么在加独占锁时,直接查该表是否有意向独占锁,如果有就意味着表里已经有记录被加了独占锁,这样就不用去遍历表里的记录
-
对于
INSERT
、UPDATE
、DELETE
,InnoDB 会自动给涉及的数据加排它锁 -
对于一般的
SELECT
语句,InnoDB 不会加任何所,事务可以通过以下语句显示加共享锁或排它锁-
共享锁
-
排它锁
-
-
意向共享锁(IS)是指当事务准备在某行记录上加共享锁(S)时,需要先在表级别加一个 IS 锁
- 意向排它锁(IX)是指当事务准备在某行记录上加排它锁(X)时,需要先在表级别加一个 IX 锁
自增锁(AUTO-INC Lock)¶
-
在为某个字段申明
AUTO_INCREMENT
属性后,可以在插入数据时不指定该字段的值,数据库会自动给该字段赋值递增的值,这主要是通过AUTO-INC
锁实现的 -
AUTO-INC
锁是特殊的表锁机制,锁不是在一个事务提交后才释放,而是在执行完插入语句后就会立即释放 -
AUTO-INC
锁在对大量数据进行插入的时候,会影响插入性能,因为另一个事务中额插入会被阻塞-
因此,在 MySQL 5.1.22 版本开始,InnoDB 存储引擎提供了一种轻量级锁来实现自增
-
一样是在插入数据的时候,会为被
AUTO_INCREMENT
修饰的字段加上轻量级锁,给该字段赋值一个自增的值后就释放这个轻量级锁,而不需要等待整个插入语句执行完之后才释放锁 -
InnoDB 存储引擎提供了一个
innodb_autoinc_lock_mode
的系统变量,用来控制选择用AUTO-INC
锁还是轻量级锁
-
页级锁¶
- 页级锁是 MySQL 中锁定粒度介于行级锁和表级锁之间的一种锁
- 表级锁速度快,但冲突多;行级锁冲突少,但速度慢;因此采取了折中的页级锁,一次锁定相邻的一组记录
- BDB 存储引擎支持页级锁
行级锁¶
简介¶
- 在 InnoDB 事务中,行锁通过给索引上的索引项加锁来实现
- 只有通过索引条件检索数据,才会使用行级锁,否则将使用表级锁
- 行级锁同样分为共享锁和排它锁,以及加锁前需要先获得的意向共享锁和意向排它锁
- 行锁是在需要的时候才加上的,但并不是不需要了就立即释放,而是要等到事务结束时才释放
锁实现方式¶
记录锁(Record Lock)¶
- 必须为唯一索引列或主键列,否则上述语句加的锁就会变成临键锁
- 查询语句必须为精准匹配(
=
),否则也会退化为临键锁 - 在 MySQL 中,行级锁并不是直接锁记录,而是锁索引
- 如果一条语句操作了主键索引,MySQL 会锁定这条主键索引
- 如果一条语句操作了非主键索引,MySQL 会先锁定该非主键索引,再锁定相关的主键索引
间隙锁(Gap Lock)¶
- 间隙锁基于非唯一索引,它锁定一段范围内的索引记录
- 产生间隙锁的条件
- 使用普通索引锁定
- 使用多列唯一索引
- 使用唯一索引锁定多行记录
临键锁(Next-Key Lock)¶
- 临键锁是一种特殊的间隙锁,通过临键锁可以解决幻读的问题
- 每个数据行上的非唯一索引列上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右开区间的数据
- InnoDB 中行级锁是基于索引实现的,临键锁只与非唯一索引列有关,在唯一索引列(包括主键列)上不存在临键锁