数据库的隔离级别和 MVCC

MVCC (Multi-Version Concurrency Control),多版本并发控制。数据库实现并发访问请求,就是基于 MVCC 实现的。

首先了解下数据库事物的隔离级别。

隔离级别

  • Read Uncommiteed 读未提交
    读取未提交的数据,即其他事物已经修改但还未提交的数据,这是最低的隔离级别。
  • Read committed 读已提交
    读取已提交的数据。在一个事物中,对同一条数据,可能会出现读取不一致现象。
  • Repeatable Read 可重复读
    可重复读取,在一个事物中,对同一条数据,确保多次读取的结果一样。(Mysql 默认隔离级别)
  • Serializable 序列化
    串行执行,数据库中的事物都是串行执行,不能并行执行,效率最差。

隔离级别主要是为了实现读操作不需要加锁, 从而提高数据库的性能。

不同隔离级别出现的问题

隔离级别 脏读 幻读 不可重复读
读未提交
读已提交
可重复度
序列化

Read Uncommiteed 和 Serializable 不需要使用多版本控制技术就可实现。
Read Uncommiteed :直接修改原始数据即可,其他事物查看数据的时候直接可以查看到,无须其他操作即可实现。
Serializable: 所有的事物都是串行执行的,只需要一个独占锁即可实现。

其中Read committed 和 Repeatable Read 两种事物隔离使用到 MVCC 进行实现的。

MVCC 实现原理

MVCC (Multi-Version Concurrency Control),多版本并发控制。MVCC 对每行数据维护多个版本。可以实现读操作不需要加锁,即可实现在同一个事物中多次读取一条数据,结果都是一致的。

MySql InnoDB存储引擎为例,InnoDB 在表中增加了两个隐藏字段。每个事物都是一个事物ID,其中一个列存储了修改时的事物ID,另一个列存储的是删除这条数据的事物ID。每开启一个事物都会生成一个自增的事物ID,当查询一条数据时,都会用当前的事物ID,和隐藏列中的事物ID进行对比,然后根据不同的事物隔离级别来决定是否返回该行数据。

下面对 Select、Delete、 Insert、 Update 四种操作了解 MVCC 的实现原理

创建一个表,表中有两个字段 id、name。MVCC 中增加两个隐藏列 update_version、delete_version。
update_version: 存储修改时,当前事物的ID
delete_version: 存储删除时,当前事物的ID。

Insert

假设当前事物的ID=1

插入一条数据时,update_version 存储当前事物的ID,。

id name update_version delete_version
1 张三 1

Update

当前事物ID=2

修改一条数据时,会新把原来的行复制一份,并把之前的那条数据delete_version 列设置成当前的事物ID 2,标记当前数据为删除,新插入的数据 update_version 设置成当前事物ID 2。

id name update_version delete_version
1 张三 1 2
1 张小三 2

Delete

当前事物ID=4

删除数据时,直接把 delete_version 这个字段设置为当前的事物ID 4.

id name update_version delete_version
1 张三 1 2
1 张小三 2 4

Select

查询必须满足以下两种条件才能返回:

  • 行的 update_version 版本号小于等于当前事物ID
  • 行的 delete_version 版本无值或大于当前事物ID
Select 示例一

比如事物ID=3, 查询 id=1 的数据

id name update_version delete_version
1 张三 1 2
1 张小三 2

查询条件为:id=1 and update_version<=3 and delete_version>3
查询出来的数据应该是 “张小三” 这条数据。

Select 示例二

假设,事物ID 3 执行的查询时间比较长,这时事物4开始删除这条数据,并提交,然后事物ID=3 的查询才开始执行,应该是能查询到 id=1 的数据。

事物ID=4 删除后的数据。

id name update_version delete_version
1 张三 1 2
1 张小三 2 4

查询条件为:id=1 and update_version<=3 and delete_version>3
查询结果应该为 “张三” 这条数据。