1.1.1. 锁

如何避免「脏读」「不可重复读」「幻读」

使用 MVCC 方案

MVCC 中,会通过生成 ReadView ,通过 ReadView 找到符合版本的记录。查询语句只会读到已经提交过的事务的更改,没提交过的是看不到的。而写操作是肯定是针对最新版本的记录,采用 MVCC 时,读-写并不冲突。

RC 下,一个事务每次 SELECT 时都会生成一次 ReadView,ReadView 确保不会读到其他事务没提交的数据,也就避免了脏读。 RR 下,一个事务只会在第一次 SELECT 时生成 ReadView,之后 SELECT 都会复用这个 ReadView 可以避免不可重复度和幻读。

对读写进行加锁

读-写跟写-写一样,进行排队

脏读:脏读产生的原因是一个事务读取到另一个事务未提交的数据,而当对数据进行加锁时,另一个事务在当前事务未提交之前必须等待事务提交才能访问数据,所以避免了脏读。 不可重复读:不可重复读产生的原因是,当前事务读取了数据,另一个事务对数据修改提交之后,当前事务再次读取数据会不一致。当对这个数据进行加锁后,另一个事务无法修改数据,则避免了不可重复读。 幻读:幻读是当前事务读取一个范围内的数据,另一个事务在满足当前事务查询条件下插入了一条记录,导致当前事务再次查询数据时,会得到多的这条记录。当当前事务对这个范围内的数据都加锁时,另一个事务是无法进行插入数据的,必须等当前事务提交后,才能执行。所以避免了幻读。

一致性读

事务利用 MVCC 进行的读取操作称之为 一致性读,或者一致性无所读。

锁定读

  • 共享锁(Shared Locks):S 锁,即事务读取一条记录前,先要获取该记录的 S 锁。
  • 排它锁(Exclusive Locks):X 锁,即事务修改一条数据前,先要获取该记录的 X 锁。

兼容性如下图: Shared-Exclusive-Lock

X 锁与任何锁都不兼容,S-S 兼容的。

锁定读的语句:

# 加 S 锁
SELECT ... LOCK IN SHARE MODE;

# 加 X 锁
SELECT ... FOR UPDATE;

写操作无非三种:

  1. DELETE:对一条记录 DELETE,需要先在 B+ 树中,找到这条记录,然后获取 X 锁,然后执行删除操作。
  2. INSERT:一般情况下,插入操作不加锁。
  3. UPDATE:其过程是先 DELETE,再 INSERT。

多粒度锁:

  1. 意向共享锁,英文名:Intention Shared Lock,简称 IS 锁,即当事务想对某条记录加 S 锁时,需要先在「表」上加 IS 锁。
  2. 意向独占锁,英文名:Intention Exclusive Lock,简称 IX 锁。即当事务相对某个记录加 X 锁时,需要先在「表」上加 IX 锁。

兼容性: lock-type-compatibility-matrix

意向锁之间是兼容的,IX - IX, S-S 是兼容的,其余的都不兼容。

行锁和表锁

表级别的 X 锁和 S 锁

  • 对某个表进行 ALTER TABLE 和 DROP TABEL 这类 DDL 时,会加表锁。
  • 表级别的 IS 和 IS 锁。
  • 表级别的 AUTO-INC 锁,听名字就跟主键自增有关,AUTO_INCREMENT。每次执行插入操作时,都会在表级别加个 AUTO-INC 锁,确保主键是连续的。

行级别的锁

  • 正常的 X 和 S 锁。 X-S-Locks
  • GAP LOCKS:间隙锁(开区间),可以防止幻读。比如这个,在 number 值为 8 之间加了间隙锁,意味着事务不允许其他事务在 number (3, 8) 进行插入操作。只有当前事务提交后,才可以 GAP-LOCKS

如果把间隙锁加在 20 上,那么后面所有区间(20,+∞)都不允许其他事务进行插入操作。

GAP-LOCKS-2

  • Next-Key Locks:可以说是 GAP LOCKS 的升级版(闭区间),可以为 (3,8] 之间进行加锁。

Nest-Key-Locks

死锁

死锁:指多个事务相互竞争同一资源相互占用,并且请求对方占用资源,导致的恶心循环。

如何解决:

  1. 以固定顺序访问,避免交叉等待锁的情况。
  2. 大事务拆小。业务允许情况下。
  3. 在同一事务中,缩小锁定行数。减少锁定行数,就减小了死锁概率。
  4. 降低隔离级别。从 RR 降低到 RC,避免很多因为 GAP 锁造成的死锁。
  5. 为表添加合理的索引。 如果不走索引则会对每一行进行加锁。

参考

浅谈数据库并发控制 - 锁和 MVCC 『浅入浅出』MySQL 和 InnoDB 数据库两个神器【索引和锁】 - Java知识点大全 - SegmentFault 思否

Copyright © Kagami丶 2019 all right reserved,powered by Gitbook该文件修订时间: 2019-12-10 21:47:13

results matching ""

    No results matching ""