GreenPlum架构之MVCC

Greenplum数据库三大特性:Shared-nothing、Mpp、MVCC。

本文介绍GrrenPlum的MVCC架构。GreenPlum作为分布式数据库,与传统事务型数据库系统通过锁机制来控制并发访问的机制不同, GPDB使用多版本控制(Multiversion Concurrency Control/MVCC)来保证数据一致性。MVCC意味着在查询数据库时,看到的只是数据的快照,可以确保当前的事务不会看到其他事务在相同记录上的修改。据此为数据库的每个事务提供事务隔离。

MVCC以避免给数据库事务显式锁定的方式,最大化减少锁争用以确保多用户环境下的性能。在并发控制方面,使用MVCC而不是使用锁机制的最大优势是, MVCC对查询(读)的锁与写的锁不存在冲突,并且读与写之间从不互相阻塞。

数据库中常见的并发技术有:

  • MVCC- Multi version COncurrency Control 多版本并发控制
  • S2PL-Strict two-phase Locking 严格的两阶段锁
  • OCC-optimistic Concurrency Control 乐观锁

MVCC特点:

  • 每个写操作会创建数据项目的新版本,同时保留旧版本
  • 允许GP在读写的同时仍然提升并发特性
  • 读操作不会阻塞写操作,写操作也不会阻塞读操作

MVCC中快照的概念:

用来跟踪数据库中某个时间点所有事务运行的状态。Greenplum中快照的实现方式是通过在每个数据对象(如行、页、表)上维护多个版本的数据,并每个版本都有一个时间戳。快照只是一个逻辑概念,实际上并没有真正的数据副本。每个事务只是通过时间戳来确定自己所能看到的数据版本,而不是真正地复制一份数据。这样可以节省存储空间,并提高性能。

比如在Read Committed隔离级别下,当前查询可以读取到已提交的事务,但是不能读取到未提交的事务,此时查询开始时生成的快照,使用快照判断事务状态,只读取已提交事务。

Greenplum中表的布局--隐藏字段

创建测试表插入测试数据

--创建测试表
create table test_mvcc(
id int,
name varchar(100)
);
--插入测试数据
insert into test_mvcc 
select gs,'name-'||gs from generate_series(1, 10000) gs;
--
select * from test_mvcc;

隐藏字段解读:

select xmin,xmax,ctid,tm.* from test_mvcc tm where id=1;

--结果为:
xmin	   xmax	   ctid	    id	  name
1823425	   0	   (0,1)	1	  name-1

 字段解释:

  • Xmin:创建Tuple元组的事务ID
  • Xmax:删除Tuple元组的事务ID,有时用于行锁
  • Ctid:指向下一个版本Tuple元组的指针,由两个成员(blockerbumber:offset)组成【 blockerbumber-配置id。offset-item下标,可以唯一标识一个tuple 即唯一一行】

结果解读:

表明该行数据是由1823425事务创建,xmax=0说明没有被删除,不存在的事务。

 快照+可见性-实现MVCC

实验一:删除操作:

在session-1窗口下开启事务,执行删除操作:

begin;
delete from test_mvcc tm where id=1;

在session-1窗口下查询对应数据:

select xmin,xmax,ctid,tm.* from test_mvcc tm where id=1;

--结果为
xmin	xmax	ctid	id	name
1823425	1823755	(0,1)	1	name-1

因为Read Committed隔离级别,未提交事务可见,该行数据仍然存在。但是可以发现xmax字段值更新,表明1823755事务正在删除改行数据,但是未提交或者已经回滚。

实验二:更新操作:

查看初始状况:

select xmin,xmax,ctid,tm.* from test_mvcc tm where id=2;

--结果
xmin	xmax	ctid	id	name
1823066	0	    (0,1)	2	name-2

在session-1窗口下开启事务,执行更新操作:

begin;
update test_mvcc set name = 'test-2' where id=2;
select xmin,xmax,ctid,tm.* from test_mvcc tm where id=2;
--执行结果
xmin	xmax	ctid	 id	 name
1823460	0	    (3,212)	 2	 test-2

同一事务中,可以看数据的xmin变化,并且name已经发生变化。虽然当前事务未提交,但是该事务中可以看到数据变化。

在session-2窗口下执行查询:

select xmin,xmax,ctid,tm.* from test_mvcc tm where id=2;
--查询结果
xmin	xmax	  ctid	 id	 name
1823066	1823460	  (0,1)	 2	 name-2

该行数据的name未发生变化,但是xmax变为1823460事务id,表明1823460事务在修改数据但是未提交或者已回滚。

Greenplum中的并发

并发读一定不会冲突,但是在MVCC架构中如何处理并发写/更新呢?

事务并发写时,如果发现事务快照中存在未提交事务,则等待事务完成时在写入。

 MVCC导致的清理需求

由于MVCC使用快照的方式实现了多版本的高并发,在实验二中可以看到更新操作时实际上创建了一个新的元组,所以在大量写操作过后,需要清理旧的元组。可以通过VACUUM执行操作,避免表膨胀的问题。

清理数据的内容:

  • 旧的元组
  • 元组的指针,即指向旧元组的指针
  • 索引项

MVCC引出的其他两个问题:

  • 如何清理表中重复数据?--参考Ctid
  • 如何进行VACUUM表空间的清理
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇

)">
下一篇>>