【MySQL】锁

211 阅读3分钟

这是我参与更文挑战的第5天,活动详情查看:更文挑战

一、前言

解决脏读、不可重复读、幻读问题:基于MVCC机制(即, undo log 版本链条 和 ReadView

那多个事务更新同一行数据时,是如何避免脏写的?

依靠:锁机制。 依靠此机制,可保证多个事务更新同一行数据的时候串行化执行。

要更新一行数据:必须把它所在的数据页从磁盘文件里读取到 缓存页 里才能更新。

即:数据和关联的锁数据结构都是在内存,操作也在内存

MySQL 的锁机制跟 Java里的锁机制,思路完全类似的。

模拟事务更新数据流程

模拟步骤:

  1. 事务A 更新指定数据
  2. 事务B 更新相同数据
  3. 事务A 更新完成并提交

  1. 初识状态:事务A 更新一行数据

事务A 对那行数据加锁,如图:

因为这行数据没有加锁,所以事务A 直接对这个操作进行加锁。

lock1.png


  1. 事务B 更新这行数据

这时候事务B 也想操作这行数据,发现已经有事务操作并加锁了,事务B 生成一个锁数据结果,并将自己的等待状态设置为 true,如图:

lock2.png


  1. 事务A 更新完并提交

事务A 更新完并提交后,会把自己的锁给释放掉。 锁一旦释放,就会唤醒其他等待的事务。

如图:

lock3.png



二、锁划分

MySQL 锁有:

  • 共享锁
  • 独占锁
  • 互斥锁
  • 表级锁

(1)共享锁 与 独占锁

MySQL 主要:共享锁(Share) 和 独占锁(Exclude

事务运行的时候,加的是独占锁(Exclue,也叫 X锁)。

  • 其他事务要更新这行数据,都要加独占锁并在锁后等待。

  • 其他事务可以读取到这行数据,不需要加锁。

    依靠的是 MVCC 机制,解决频繁加锁互斥。


共享锁(S 锁):执行查询时候加锁

即,在查询语句后面加上 lock in share mode

-- 例如:
SELECT * FROM table LOCK IN SHARE MODE;

加了共享锁,不能再加独占锁(即,他人不能再来更新)。

举个例子:中国土地归人民所有,但不能一人独占一块地。

共享锁和独占锁规律如下:

共享锁独占锁
共享锁不互斥互斥
独占锁互斥互斥

互斥锁:查询数据之后还要执行更新操作,其他事务更新不了这个数据。

-- 例如:
SELECT * FROM table FOR UPDATE;

(2)表级锁

执行 DDL 语句的时候,会默认在表级别加表锁,例如 ALTER TABLE 操作。

表锁,语法如下:

-- 加表级共享锁
LOCK TABLES xxx READ

-- 加表级独占锁
LOCK TABLES xxx WRITE

另外两个情况会加表级锁:

  • 如果有事务在表里执行增删改操作,那在行级会加独占锁,同时会在表级加一个意向独占锁
  • 如果有事务在表里执行查询操作,那么会在表级加一个意向共享锁

关系如下:

独占锁意向独占锁共享锁意向共享锁
独占锁互斥互斥互斥互斥
意向独占锁互斥不互斥互斥不互斥
共享锁互斥互斥不互斥不互斥
意向共享锁互斥不互斥不互斥不互斥