数据库的隔离级别和 MVCC

2020-03-24 10:57:46 浏览数 (1)

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 查询结果应该为 “张三” 这条数据。

0 人点赞