前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PostgreSQL MVCC可见性判断

PostgreSQL MVCC可见性判断

原创
作者头像
yzsDBA
修改2020-03-13 10:19:55
1.6K0
修改2020-03-13 10:19:55
举报
文章被收录于专栏:PostgreSQL研究与原理解析

1、知识准备

1)Tuple格式头HeapTupleHeaderData

typedef struct HeapTupleFields

{

TransactionId t_xmin;   /* inserting xact ID */

TransactionId t_xmax;   /* deleting or locking xact ID */

union

{

CommandId t_cid;   /* inserting or deleting command ID, or both */

TransactionId t_xvac; /* VACUUM FULL xact ID */

}t_field3;

}HeapTupleFields;

其中:

t_xmin:存储的是产生这个元组的事务ID,可能是insert或者update语句

t_xmax:存储的是删除或者锁定这个元组的事务ID

t_cid :包含cmin和cmax两个字段,分别存储创建这个元组的Command ID和删除这个元组的Command ID

t_xvac:存储的是VACUUM FULL 命令的事务ID

PostgreSQL主要就是通过t_xmin,t_xmax,cmin和cmax,ctid,t_infomask来唯一定义一个元组(t_xmin,t_xmax,cmin和cmax,ctid实际上也是一个表的隐藏的标记字段)。

2)Clog

PostgreSQL 在 CLOG 中维护事务的状态,持久化存储在 pg_xact 目录下,为了访问高效,会在内存中维护一块共享内存用于缓存 CLOG 的内容。

PG定义有四种事务状态:

#define TRANSACTION_STATUS_IN_PROGRESS 0x00

#define TRANSACTION_STATUS_COMMITTED 0x01

#define TRANSACTION_STATUS_ABORTED 0x02

#define TRANSACTION_STATUS_SUB_COMMITTED 0x03

Clog文件以页为单位。数组下标是事务ID,参考TransactionIdGetStatus这个函数。数组内容是事务状态,每个事务状态占用2bit即可。一个页面8K,可以存储8K*8/2=32K个事务状态。Clog buffer大小为Min(128, Max(4, NBuffers / 512)),初始化函数为CLOGShmemInit。启动时会从pg_xact读取事务状态加载到内存。系统运行过程中,vacuum会定时将不再使用的clog文件清理。

3)Hint

在进行可见性判断时,需要获取事务的状态,即元组中 t_xmin 和 t_xmax 的状态,这些事务状态保存在 CLOG 中,为加速获取事务状态的过程,PostgreSQL 引入了 Hint Bits。

所有 Hint Bits,就是把事务状态直接记录在元组头中(HeapTupleHeaderData),避免频繁访问 CLOG,元组头中对应的标识位如下:tuple->t_infomask

#define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */

#define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */

#define HEAP_XMIN_FROZEN (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)

#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */

#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */

#define HEAP_XMAX_IS_MULTI 0x1000 /* t_xmax is a MultiXactId */

PostgreSQL 并不会在事务提交或者回滚时主动更新元组上的 Hint Bits,而是等到访问该元组并进行可见性判断时,如果发现 Hint Bits 没有设置,则从 CLOG 中读取并设置,否则直接读取 Hint Bits 的值。判断可见性过程中设置 Hint Bits 的函数入口为 SetHintBits。这里的访问可能是 VACUUM,DML 或者 SELECT。

因此,Hint Bits 可以理解为是事务状态在元组头上的一份缓存。

4)Hint与日志

在开启 checksum 或者 GUC 参数 wal_log_hints 为 true 的情况下,如果 checkpoint 后第一次使页面 dirty 的操作是更新 Hint Bits,则会产生一条 WAL 日志,将当前页面写入 WAL 日志中(即 Full Page Image),避免产生部分写,导致数据 checksum 异常。注意,以上写 Full Page Image 日志的行为与是否开启 full_page_writes 没有关系。因此,在开启 checksum 或者 GUC 参数 wal_log_hints 为 true 时,即便执行 SELECT,也可能更改页面的 Hint Bits,从而导致产生 WAL 日志,这会在一定程度上增加 WAL 日志占用的存储空间。

2、快照判断

判断一个事务是否在快照,即针对这个快照是否还在in progress:

1)大于等于snap->xmax:未来事务,不可见

2)小于snap->xmin:已结束事务,可见

3)[snap->xmin,snap->xmax):查看CLOG。Commit状态:可见;in progress和abort状态:不可见

3、MVCC判断可见性

可见性判断规则可归纳为:

/* t_xmin status = ABORTED */

Rule 1: IF t_xmin status is 'ABORTED' THEN

            RETURN 'Invisible'

        END IF

/* t_xmin status = IN_PROGRESS */

        IF t_xmin status is 'IN_PROGRESS' THEN

            IF t_xmin = current_txid THEN

Rule 2:         IF t_xmax = INVALID THEN

                    RETURN 'Visible'

Rule 3:         ELSE  /* this tuple has been deleted or updated by the current transaction itself. */

                    RETURN 'Invisible'

                END IF

Rule 4:     ELSE   /* t_xmin ≠ current_txid */

                RETURN 'Invisible'

            END IF

         END IF

/* t_xmin status = COMMITTED */

         IF t_xmin status is 'COMMITTED' THEN

Rule 5:     IF t_xmin is active in the obtained transaction snapshot THEN

                RETURN 'Invisible'

Rule 6:     ELSE IF t_xmax = INVALID OR status of t_xmax is 'ABORTED' THEN

                RETURN 'Visible'

            ELSE IF t_xmax status is 'IN_PROGRESS' THEN

Rule 7:         IF t_xmax =  current_txid THEN

                    RETURN 'Invisible'

Rule 8:         ELSE  /* t_xmax ≠ current_txid */

                    RETURN 'Visible'

                END IF

            ELSE IF t_xmax status is 'COMMITTED' THEN

Rule 9:         IF t_xmax is active in the obtained transaction snapshot THEN

                    RETURN 'Visible'

Rule 10:        ELSE

                    RETURN 'Invisible'

                END IF

            END IF

        END IF

4、参考

https://yq.aliyun.com/articles/675939

http://blog.itpub.net/6906/viewspace-2562652/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、知识准备
  • 2、快照判断
  • 3、MVCC判断可见性
  • 4、参考
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档