了解更多Greenplum技术干货,欢迎访问Greenplum中文社区网站
2020的夏天已经接近尾声,《深入浅出Greenplum内核》系列直播也已经成功举办了五场活动,内容覆盖了Greenplum架构、执行引擎、查询优化、B树索引(均插入之前的总结文章链接),相关视频可前往B站的Greenplum中文社区频道进行回顾观看。
8月28日,Greenplum原厂内核研发陈金豹从优缺点、实现细节、和空间重用三个角度深度揭秘了Greenplum的MVCC并发控制。本文将带领我们回顾精华内容。
MVCC,全称是Multi-version Concurrency Control,即多版本并发控制。
大家可能会有个疑问,为什么我们需要了解MVCC呢?其实不管是对于数据库开发者,或者是对于DBA,MVCC都是非常重要的。如果你是一个Postgres/Greenplum生态的开发者,MVCC作为整个存储体系中最重要的一环,是需要牢固掌握的知识点之一。如果你是一个DBA, 了解MVCC有助于理解数据库并发查询的行为,同时能够管理MVCC对性能的影响。最重要的是,MVCC会有一些清理垃圾的需求,即存储空间的重用,如果能够了解MVCC的原理,对于这些操作,你将更加得心应手。
首先给大家介绍一下常用的并发控制技术,一共三种:
-
第一种就是我们今天要着重介绍的——Multi-version Concurrency Control(MVCC),多版本并发控制
-
第二种是Strict Two-Phase Locking(S2PL),严格的两阶段锁
-
第三种是Optimistic Concurrency Control(OCC),乐观锁
目前市面上的数据库用的基本就是这三种并发控制技术,如果大家对于后两种技术比较感兴趣,可以去百度搜索相关资料,本文将不做赘述。
在将MVCC的实现前,我们先来了解几个概念:
事务和隔离
要了解多版本并发控制,我们需要先了解两个概念:事务和隔离。
事务
第一个概念就是事务,事务的本质就是将多个步骤捆绑成一个原子操作。比如先INSERT,然后UPDATE,再SELECT三个执行语句,在事务中,我们会把这三个执行步骤捆绑成一个原子的步骤,并希望这一个原子的步骤或者全部成功,即所有的语句均能执行成功,或者全部不成功。如果中间出现了故障导致事务无法完成,则所有步骤都不会影响数据库,此时会回滚到初始状态。
由于事务的这种特性,事务执行的中间状态是不会被别的事务看到的。大家想一想,如果这个事务的中间状态会被另外一个事务看到,因为已经对其他事务产生了影响,回滚将没有办法完成。这里就涉及到了另一个概念:隔离。
隔离
由于事务是具有原子性的,因此事务和事务之间,我们是不希望看到中间状态的,因此事务和事务之间要有隔离。SQL标准里把事务隔离级别分成了四级,
-
Read Uncommunitted(读未提交)
-
Read Committed(不可重复读)
-
Repeatable Read(可重复读)
-
Serializable (串行化)
我们来简单介绍一下这四个隔离级别是什么含义。
1. Read Uncommited
第一个级别Read Uncommitted是可以脏读的。即不管事务进行到哪一步,该事务所做的改动对别的事务均可见。按理说,在一个严肃的数据库里,这似乎是不应该发生的事情,因为我们希望事务是一个原则性的操作,如果他失败了需要回滚,所以说他的中间状态一定是不能被别的事务看到的,可见这是一个非常低的级别,是一个通常情况下,很难被人们接受的一个级别。
2. Read Committed
第二个级别叫Read Committed。在这个级别下,是不支持脏读的,但一旦事务提交了,它所造成的影响就对别的事务可见了。基本满足了原子性的要求。
但是Read Committed存在一个问题。如果一个事务中有很多条语句,那么可能会出现,在不同的语句中看到的数据集不一样的情况。
例如,事务一和事务二并发进行