1、MVCC是什么?

MVCC:multiversion concurrentcy control ,翻译成中文就是多版本并发控制。

 

2、MVCC是为了解决什么问题出现的?

 

其实顾名思义,MVCC是为了解决并发问题而出现的。我们知道数据库并发会产生并发一致性的问题:比如脏读、不可重复读、幻读。

解决并发一致性的问题,常见的解决方案是加锁。比如让所有的read事务都等待write事务完成,所以这样的效率是很差的。MVCC就是它的替代(补充)方案。

 

 

3、MVCC有什么具体的表现?

 

举个例子:当数据库更新数据时,并不是将老的数据删除,再把新的数据覆盖上去,它会把老的数据做一个标记隔离出去(Old Version),然后再新增新的数据作为一个新的版本。这个时候,新老数据都是存在在数据库里的。

基于这个特性,读写事务可以分别在不同的行版本上工作,因此能够在互不冲突的情况下并发执行。

 

 

4、MVCC的机制?

 

事务ID

 

在PostgreSQL中,每个事务都有一个唯一的事务ID,被称为XID。注意:除了被BEGIN - COMMIT/ROLLBACK包裹的一组语句会被当作一个事务对待外,不显示指定BEGIN - COMMIT/ROLLBACK的单条语句也是一个事务。

数据库中的事务ID递增。可通过txid_current()函数获取当前事务的ID。

 

隐藏字段

 

Postgresql中,对于每一行数据(称为一个tuple),包含有4个隐藏字段。这四个字段是隐藏的,但可以直接访问。

xmin:在创建(insert)记录(tuple)时,记录此值为插入tuple的事务id。

Xmax:默认值是0,在删除tuple时,记录此值。

Cmin和cmax 标示在同一个事务中多个语句命令的序列值,从0开始,用于同一个事务中实现版本可见性判断

 

简单的来说

PostgreSQL中的MVCC实现原理可简单概括如下:

1)数据文件中存放同一逻辑行的多个行版本(称为Tuple);

2)每个行版本的头部记录创建该版本的事务ID以及删除该行版本的事务的ID(分别称为xmin和xmax);

3)每个事务的状态(运行中,中止或提交)记录在pg_clog文件中;

4)根据上面的数据并运用一定的规则每个事务只会看到一个特定的行版本。

 

 

5、MVCC的应用

 

在事务方面的作用主要体现在原子性和隔离性。

 

MVCC保证原子性

原子性(Atomicity)指是一个事务是一个不可分割的工作单位,事务中包括的所有操作要么都做,要么都不做。

对于插入操作,PostgreSQL会将当前事务ID存于xmin中。对于删除操作,其事务ID会存于xmax中。对于更新操作,PostgreSQL会将当前事务ID存于旧数据的xmax中,并存于新数据的xin中。换句话说,事务对增、删和改所操作的数据上都留有其事务ID,可以很方便的提交该批操作或者完全撤销操作,从而实现了事务的原子性。

 

MVCC保证事物的隔离性

隔离性(Isolation)指一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

 

MVCC提交读

提交读只可读取其它已提交事务的结果。PostgreSQL中通过pg_clog来记录哪些事务已经被提交,哪些未被提交。


MVCC可重复读

相对于提交读,重复读要求在同一事务中,前后两次带条件查询所得到的结果集相同。实际中,PostgreSQL的实现更严格,不仅要求可重复读,还不允许出现幻读。它是通过只读取在当前事务开启之前已经提交的数据实现的。结合上文的四个隐藏系统字段来讲,PostgreSQL的可重复读是通过只读取xmin小于当前事务ID且已提交的事务的结果来实现的。

 

6、MVCC的优势


  • 使用MVCC,读操作不会阻塞写,写操作也不会阻塞读,提高了并发访问下的性能

  • 事务的回滚可立即完成,无论事务进行了多少操作

  • 数据可以进行大量更新,不像MySQL和Innodb引擎和Oracle那样需要保证回滚段不会被耗尽

 

7、MVCC的缺点

事务回卷:事物ID有限制,会有事务回卷的现象发生。这样带来一个逻辑问题:突然所有记录都变成了发生在将来的事务所产生的,而所有新事物也都没有办法访问这些旧记录了。

大量过期数据占据磁盘并降低查询性能

https://mp.weixin.qq.com/s/kEU3YXkbqB3tC1NpdHwWLQ