Greenplum列存压缩表事务机制
事务隔离级别
我们知道Heap表的事务隔离是通过MVCC实现,但是在列存表没有记录xmin,xmax等多版本信息,仅仅记录了块的元信息以及数据,那么它是如何实现事务隔离的?
仍然借助于Heap表,没创建一个列存表,同时创建一个heap辅助表表,通过select * from pg_appendonly
可以看到辅助表的OID(segrelid),这个辅助表几面记录了什么呢?
typedef struct AOCSVPInfoEntry
{
int64 eof;
int64 eof_uncompressed;
} AOCSVPInfoEntry;
从这个结构体可以看出来,辅助表记录了当前事务在列存文件中可见的结尾偏移量。如果其他连接插入了数据,列存文件变大了,但是当前事务还是只能看到插入之前的结尾偏移量,多余的数据是看不到的。
如图所示,B事务新增的数据的EOF位置存在Heap表中,而Heap表满足MVCC的,所以A事务看不到B事务中Heap表的变更,继续使用A事务开始的是EOF。
总之,列存的事务原理是靠辅助Heap表实现的。
崩溃恢复
机器可能宕机、断电等,事务需要回滚,数据可能部分写,对于这些场景Greenplum列存是如何处理的呢?
cancel/kill等引起的正常事务回滚
在Greenplum列存表原理里面我们已经提到,并发导入是靠多个文件实现,也就是说每个Insert连接只会负责一个列文件,假设事务开始的时候文件EOF为EOF_start, 导入后变成EOF_end,如果事务回滚,辅助Heap表里面记录的EOF回滚到事务开始的EOF_start,回滚完成。下次事务导入将会从EOF_start继续增加数据,覆盖EOF_start--EOF_end之间的数据。
数据部分写
Greenplum列存表是不写XLOG的,那么它是如何做到崩溃之后恢复的呢?
- 每次commit提交强制做fsync,所以只要事务提交,那么磁盘数据就是一致的,崩溃恢复不影响。
- 新的事务导入数据,强制新增block,不能使用上一个事务的block,即便上一个事务的block还没有写满。这样就不会存在复用上一个事务block写数据时写到一半出问题丢失上个事务block的数据。因此强烈不建议使用每次insert一条方式导入数据,这样会产生的大量的block,每条记录都对一个block,影响扫描性能。
最后更新:2017-08-15 15:32:27
上一篇:
云服务器 ECS 实例自定义数据:自定义实例的管理员账号
下一篇:
世平敏感信息安全检查系统云端版登陆阿里云市场
pyinotify:在 Linux 中实时监控文件系统更改
RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
SSH(spring+springmvc+hibernate)框架快速上手
awk 系列:如何使用 awk 语言编写脚本
SVN commit:remains in tree-conflict错误的解决办法
ECS API中Signature错误的排查方法
Android-Universal-Image-Loader图片异步加载并缓存
端口检测工具Fport的使用
Ubuntu Server 8.0.4安装小记
Go语言与数据库开发:01-04