PostgreSQL mvcc可见性判断

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: PostgreSQL mvcc可见性判断

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_PROGRESS0x00
#define TRANSACTION_STATUS_COMMITTED0x01
#define TRANSACTION_STATUS_ABORTED0x02
#define TRANSACTION_STATUS_SUB_COMMITTED0x03

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_COMMITTED0x0100/* t_xmin committed */
#define HEAP_XMIN_INVALID0x0200/* t_xmin invalid/aborted */
#define HEAP_XMIN_FROZEN(HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)
#define HEAP_XMAX_COMMITTED0x0400/* t_xmax committed */
#define HEAP_XMAX_INVALID0x0800/* t_xmax invalid/aborted */
#define HEAP_XMAX_IS_MULTI0x1000/* t_xmax is a MultiXactId */

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

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


4)Hint与日志


在开启 checksu 或者 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状态:不可见


3MVCC判断可见性



 

 

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


/* 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/

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
4月前
|
Oracle 关系型数据库 MySQL
一文了解PostgreSQL MVCC机制
一文了解PostgreSQL MVCC机制
229 0
|
存储 关系型数据库 Go
深入理解 PostgreSQL 中的 MVCC(多版本并发控制)机制
深入理解 PostgreSQL 中的 MVCC(多版本并发控制)机制
269 0
|
存储 算法 Oracle
PostgreSQL的MVCC vs InnoDB的MVCC
PostgreSQL的MVCC vs InnoDB的MVCC
99 0
PostgreSQL的MVCC vs InnoDB的MVCC
|
关系型数据库 分布式数据库 PolarDB
|
关系型数据库 分布式数据库 定位技术
PolarDB for PostgreSQL 开源必读手册-VACUUM处理(中)
PolarDB for PostgreSQL 开源必读手册-VACUUM处理
174 0
|
关系型数据库 分布式数据库 PolarDB
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
373 0
|
存储 缓存 关系型数据库
|
存储 SQL 并行计算
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍(中)
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍
429 0
|
存储 算法 安全
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍(下)
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍
389 0
|
关系型数据库 分布式数据库 开发工具
下一篇
DataWorks