Skip to content

事务隔离机制

隔离级别

数据库引擎通过隔离级别决定所有操作的加锁行为。

四种隔离机制可视为

  • 不加锁
  • 仅写入排他锁
  • 读共享锁、写入排他锁, 唯一索引是行锁,范围查询是范围锁,全表扫描是表锁
  • 读写表锁

隔离级别

读未提交

操作不需要加锁,会存在各种并发问题

读已提交

仅对写入操作加排他锁

因为读不需要加锁,会因事务过程中数据被修改导致不可重复读和幻读

可重复读

InnoDB 默认机制。

读加共享锁,写加排他锁。

但是因为 MVCC 的存在,默认的读是快照读,不会加共享锁。

串行化

可视为事务串行执行,所有操作加表锁,不会出现一致性问题

一致性问题

脏读(Dirty Read)

在事务中读取到别的事务写入但未提交的数据,数据可能会被回滚

写入未加排他锁,导致行可读

不可重复读(NonRepeatable Read)

在事务中读取到的数据在稍后被别的事务写入并提交,导致多次读结果不一致, 主要体现在updatedelete

读操作未对命中记录加共享锁(排他锁),导致命中记录可被其他事务写入

幻读(Phantom Read)

类似不可重复读,区别是因范围查询导致多次结果不一致, 主要体现在 insert

写入数据时未范围锁(间隙锁/临键锁),导致其他事务可写入属于该查询范围的记录。

锁种类

  1. 对于主键和唯一索引的条件查询, 会使用行锁
  2. 对于全表扫描,会使用表锁
  3. 对于非唯一索引的范围查询,会使用范围锁
    1. 对于范围查询未命中索引,使用的是间隙锁
    2. 对于范围查询命中索引,使用的是临键锁

间隙锁是包含两个相邻叶子节点的开区间

临键锁是包含两个相邻叶子节点的左开右闭区间

MVCC机制(多版本并发控制)

MVCC 机制通过对数据保存多个版本,记录事务 ID 和版本信息,实现了快照读和当前读。

快照读返回读视图生成时的快照,实现了不加锁的可重复读,提升了读写并发能力,但是会存在幻读问题。

回顾

  1. 对于常用的 MySQL InnoDB PR 隔离机制下,需要注意默认读是快照读,要区分快照读和当前读。

参考阅读