乐趣区

MYSQL锁机制

前言

本文讲述 mysql 锁定义,lock 与 latch 区别,Innodb 中的锁,强制开启 S / X 锁,自增长锁,行锁的 3 中算法,锁降级等,次要参照来自《MYSQL 技术底细 第 2 版》这本书,以及参杂了本人的一些了解。

锁定义 / 作用

为反对对 共享资源 的并发拜访,保证数据的 一致性 完整性 ,数据库所提供的一种 束缚机制。不同的数据库和不同的引擎有着不同实现形式及反对度,可分为行,页,表锁。(MyISAM 是表锁,SQL SERVER 是行级锁,InnoDB 默认也是行级锁)

行锁 页锁 表锁
MyISAM
Innodb
BDB
SQL Server

前三个都是 MYSQL 的不同引擎。

lock 与 latch(门闩 shuan)

latch 实用于短期锁定的 轻量级锁(门闩不防盗嘛),锁定工夫过长时,性能会十分差。

lock 的对象是事务,锁定的是数据库中的对象: 行、页、表,锁在 commit 或 rollback 时才会开释。
latch 分为 mutex(互斥锁)和 rwlock(读写锁),用于保障 并发线程 操作临界资源 (能够了解为共享资源) 的正确性。

latch 是面向数据库系统底层的,目前没找供用户开发的 api,除非 DBA,一般开发者根本用不到,理解即可。
lock latch
对象 事务 线程
持续时间 整个事务 临界资源
模式 行,页,表锁 mutex,rwlock
保留在 lock manager 的哈希表中 数据结构的对象中
mysql innodb 中:
    查看 latch 命令: `show engine innodb latch`
    查看 lock 命令: `show engine innodb status`

Innodb 引擎中的锁

innodb 反对行锁和表锁(不反对表锁),默认为行锁。

两种行级锁:

  1. 共享锁(S lock):容许事务读 1 行
  2. 排他锁(X lock):容许事务删除或更新 1 行

在 A 取得 S 锁后,B 可获 S 锁,但不能加 X,否则 A 会阻塞。(读不影响数据)
在 A 取得 X 锁后,B 不能再取得任何锁。(批改必须独占)

S 锁能够了解为读锁,X 锁能够了解为独占锁,且 X 优先级高于 S。

Innodb 反对多粒度锁定,容许行级、表级上的锁同时存在。(Innodb 不反对页级锁)为此推出一种新的锁形式 意向锁(Intention Lock): 将锁定的对象分为多个档次,以满足事务在更细的细粒度上加锁。

一句话概括就是,对下层对象 (页,表) 加同样的意向锁(IS/IX)。同样的意思就是记录加 S,下层对象就加 IS;同理,记录加 X,下层对象就加 IX。

所有兼容状况:(兼容就是能获取,不兼容就是要期待阻塞)
很显著,是对称矩阵哦

一致性非锁定读

一致性非锁定读 (consistent nolocking read):指的是在读取被加 X 锁的行时,不须要期待行锁的开释,会去读它的快照(snapshot)。
一个行有多个快照数据,到底读哪一个呢?
READ COMMITED 是读最新的,READ REPEATEABLE(Innodb 默认隔离级别)是读的是 本人 事务 begin 前的。(这里的场景是开启两个事务,一个查,一个改,有先后。)READ COMMITD 会毁坏隔离性(Isolation)

一致性锁定读 – 强制开启锁

尽管可反复读(默认隔离级别)保障了隔离性,但为了确保数据的一致性,咱们能够显式 强制加锁

  • SELECT … IN SHARE MODE
  • SELECT … FOR UPDATE

下面的 in share mode 是加的 S 锁。for update是加的 X 锁。

自增长锁

对字段设置 auto_incrment 时,自增计算器会保留在表中,锁会在 insert 语句之后,事务 commit 之前开释。(非凡的机制,为进步插入性能,没有抉择事务完结再开释,而是 Insert 后)。前面 MYSQL 还新增了 innodb_autoinc_mode 来进一步管制自增长。

注:Innodb 下自增列必须是索引,而且是索引的第一列(组合索引状况下),否则抛出异样。MyISAM 没有这要求。

行锁的 3 种算法

  • Record Lock : 记录锁,锁定本人的记录
  • Gap Lock:沟锁,锁本人左近的范畴,不包含本人记录(开区间)
  • Next-key Lock:范畴 + 本人,Record+Gap 联合(闭区间)

Record Lock 是锁住 索引记录 ,主键也是索引之一。
Next-key 是 行查问 select 默认采纳的锁算法,如有索引:10,13,20。则锁区间为:(-∞,10],(10,13],(13,20],(20,+∞)。
显知,gap 的话就蕴含本人,]变成了)。

next-key 这里的 next 指的就是右区间为闭区间,推理:previous-key 指的是左区间闭合。

注:主动降级:若索引中含有惟一属性(** 惟一 ** 索引),则 next-key 会主动降级为 record-key。(范畴锁——> 只锁本人)

next-key 机制的创造是为了解决 Phantom problem(幻像问题),是的 mysql 能够不到 serializable 就能够解决幻读。
幻像 :一个事务 A 在未提交时,两次 sql 的执行的后果的 数据条数 不一样,B 向其中批改的数据被 A 在第二次读走了。违反了隔离性。
脏读: A 读到了 B 中 未提交 的数据,若 B 之后回滚了,则读到了脏数据。
不可反复读: B 对 A 读到的值进行了批改,A 第二次读到的 数据值 变了。

锁降级(lock escalation)

定义:锁的粒度升高。如:行锁——> 页锁——> 表锁

作用:锁是罕见资源,降级是为了提高效率,避免零碎应用太多内存来保护锁。

Innodb 存储引擎不存在锁降级。因为它不是依据记录来产生行锁,而是依据事务拜访的每个页来治理锁,采纳 位图 形式。锁住一个页的一条与锁住多条的开销一样。

这里的 ` 页来治理锁 ` 和下面 `innodb 不反对页锁 ` 有点绕,我也没了解,我前面去查证一下。
退出移动版