您的位置:首页 > 数据库 > MySQL

【MySQL】MVCC(多版本并发控制)

2017-05-17 22:06 821 查看

一、概述

  MVCC(Multiversion Concurrency Control),即多版本并发控制。它使得大部分支持行锁的事务引擎,不再单纯的使用行锁来进行数据库的并发控制,取而代之的是,把数据库的行锁与行的多个版本结合起来,只需要很小的开销,就可以实现非锁定读,从而大大提高数据库系统的并发性能。

二、MVCC的目的

  使用MVCC的目的在于降低开销。

  锁机制可以控制并发操作,但是其系统开销较大,而MVCC可以在大多数情况下代替行级锁,使用MVCC能降低其系统开销。

  实际上,大多数的MYSQL事务型存储引擎,如InnoDB,Falcon都不仅仅使用简单的行锁机制,而是和MVCC–多版本并发控制来一起使用。

三、MVCC原理

  MVCC可以提供基于某个时间点的快照,使得对于事务看来,总是可以提供与事务开始时刻相一致的数据,而不管这个事务执行的时间有多长。所以在不同的事务看来,同一时刻看到的相同行的数据可能是不一样的,即一个行可能有多个版本。

四、MVCC具体实现

  InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,其中一列存储行被创建的“时间”,另外一列存储行被删除的“时间”。这里的“时间”并不是实际的时间值,而是系统版本号(可以理解为事务的ID),每当一个事务开始的时候,innodb都会给这个事务分配一个递增的版本号,所以版本号也可以被认为是事务号。

  在repeated read的隔离级别下,具体各种数据库操作的实现:

  1.select:满足以下两个条件innodb会返回该行数据:

  (1)该行的创建版本号小于等于当前版本号,用于保证在select操作之前所有的操作已经执行落地。

  (2)该行的删除版本号大于当前版本或者为空。删除版本号大于当前版本意味着有一个并发事务将该行删除了。

  2. insert:将新插入的行的创建版本号设置为当前系统的版本号。

  3.delete:将要删除的行的删除版本号设置为当前系统的版本号。

  4.update:不执行原地update,而是转换成insert + delete。将旧行的删除版本号设置为当前版本号,并将新行insert同时设置创建版本号为当前版本号。

  以上4条,写操作(insert、delete和update)执行时,需要将系统版本号递增。

五、例子

5.1 insert

begin;
INSERT INTO user(username) VALUES('jack');
INSERT INTO user(username) VALUES('hello');
commit;


插入两条数据,假设事务ID(系统版本号)为1,则创建时间列的值为1。

idusername创建时间删除时间
1jack1undefined
2hello1undefined
注:后面两列(创建时间、删除时间)是隐藏列,并不能看见,这里是示意图。

5.2 delete

DELETE FROM user WHERE id=1;


删除操作的时候,把事务版本号作为删除版本号,此时为2.

idusername创建时间删除时间
1jack12
2hello1undefined

5.3 update

UPDATE user SET username='world' WHERE id=2;


不执行update,而是转换成insert + delete,先标记旧的那行记录为已删除,并且删除版本号是事务版本号,然后插入一行新的记录的方式。事务ID为3。

idusername创建时间删除时间
1jack12
2hello13
2world3undefined

5.4 select

SELECT * FROM user


当前版本号为4,所以按照select的两个条件返回结果如下:

idusername创建时间删除时间
2world3undefined

5.5 综合示例

  下面来看一个综合一点的例子:有两个事务,事务ID分别为5,6。

事务5:

SELECT * FROM user WHERE id=2;


事务6:

UPDATE user SET username='Tom' WHERE id=2;


假设事务5还未执行完毕,而事务6已经执行完毕,此时表中数据为:

idusername创建时间删除时间
1jack12
2hello13
2world36
2Tom6undefined
然后事务5执行完毕,因为username=Tom那行的创建时间6>当前版本号5,而username=world那行的创建时间3>当前版本号>删除时间,由select的两个条件,得到的结果为:

idusername创建时间删除时间
2world36
  从上面这个例子我们可以简单地理解下MVCC如何代替锁的(并不准确)。

  如果使用锁,上面的操作如何进行?首先,事务5占用锁并执行,事务6阻塞,事务5执行完毕后得到查询结果并释放锁,事务6得到锁并执行自身的update操作。整个过程使用锁机制控制并发操作,但是其系统开销较大。

  而使用MVCC,通过版本检查,只获得自己需要的数据版本。我们不需要承担锁机制的开销,却能达到同样的效果。

六、MVCC的优缺点

优点:降低其系统开销。在读取数据的时候,innodb几乎不用获得任何锁,每个查询都通过版本检查,只获得自己需要的数据版本,从而大大提高了系统的并发度。

缺点:为了实现多版本,innodb必须对每行增加相应的字段来存储版本信息,同时需要维护每一行的版本信息,而且在检索行的时候,需要进行版本的比较,因而降低了查询的效率;innodb还必须定期清理不再需要的行版本,及时回收空间,这也增加了一些开销。

参考资料

innodb 多版本并发控制原理详解

轻松理解MYSQL MVCC 实现机制

MVCC浅析

mysql的mvcc(多版本并发控制)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据库 mysql 并发