对PostgreSQL cmin和cmax的理解

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

看例子:

开两个终端来对比:

在终端A:

复制代码
[pgsql@localhost bin]$ ./psql
psql (9.1.2)
Type "help" for help.

pgsql=# begin;
BEGIN
pgsql=# select xmin,xmax,cmin,cmax,* from tab01;
 xmin | xmax | cmin | cmax |    id     | cd 
------+------+------+------+-----------+----
 1878 |    0 |    0 |    0 |         1 | 1
 1884 |    0 |    0 |    0 | 999888777 | 2
(2 rows)

pgsql=# insert into tab01 values(3,'3');
INSERT 0 1
pgsql=# insert into tab01 values(4,'4');
INSERT 0 1
pgsql=# select xmin,xmax,cmin,cmax,* from tab01;
 xmin | xmax | cmin | cmax |    id     | cd 
------+------+------+------+-----------+----
 1878 |    0 |    0 |    0 |         1 | 1
 1884 |    0 |    0 |    0 | 999888777 | 2
 1885 |    0 |    0 |    0 |         3 | 3
 1885 |    0 |    1 |    1 |         4 | 4
(4 rows)

pgsql=# 
复制代码

此时的终端B:

复制代码
[pgsql@localhost bin]$ ./psql
psql (9.1.2)
Type "help" for help.

pgsql=# select xmin,xmax,cmin,cmax, * from tab01;
 xmin | xmax | cmin | cmax |    id     | cd 
------+------+------+------+-----------+----
 1878 |    0 |    0 |    0 |         1 | 1
 1884 |    0 |    0 |    0 | 999888777 | 2
(2 rows)

pgsql=# 
复制代码

然后再在终端A进行提交:

复制代码
pgsql=# commit;
COMMIT
pgsql=# select xmin,xmax,cmin,cmax,* from tab01;
 xmin | xmax | cmin | cmax |    id     | cd 
------+------+------+------+-----------+----
 1878 |    0 |    0 |    0 |         1 | 1
 1884 |    0 |    0 |    0 | 999888777 | 2
 1885 |    0 |    0 |    0 |         3 | 3
 1885 |    0 |    1 |    1 |         4 | 4
(4 rows)

pgsql=# 
复制代码

此时,再在终端B进行观察:

复制代码
pgsql=# select xmin,xmax,cmin,cmax, * from tab01;
 xmin | xmax | cmin | cmax |    id     | cd 
------+------+------+------+-----------+----
 1878 |    0 |    0 |    0 |         1 | 1
 1884 |    0 |    0 |    0 | 999888777 | 2
 1885 |    0 |    0 |    0 |         3 | 3
 1885 |    0 |    1 |    1 |         4 | 4
(4 rows)

pgsql=# 
复制代码

 继续研究cmin是咋回事:

复制代码
pgsql=# begin;
BEGIN
pgsql=# insert into tab01(id,cd) values(generate_series(5,6),'xx');
INSERT 0 2
pgsql=# select xmin,xmax,cmin,cmax,* from tab01;
 xmin | xmax | cmin | cmax |    id     | cd 
------+------+------+------+-----------+----
 1878 |    0 |    0 |    0 |         1 | 1
 1884 |    0 |    0 |    0 | 999888777 | 2
 1885 |    0 |    0 |    0 |         3 | 3
 1885 |    0 |    1 |    1 |         4 | 4
 1886 |    0 |    0 |    0 |         5 | xx
 1886 |    0 |    0 |    0 |         6 | xx
(6 rows)

pgsql=# 
复制代码

可以说cmin可理解为一个事务里,执行了几次sql命令的顺序。

那么cmax呢?在前面的基础上继续执行,居然没有看到区别:

复制代码
pgsql=# update tab01 set id=2 where cd = '2';
UPDATE 1
pgsql=# select xmin,xmax,cmin,cmax,* from tab01;
 xmin | xmax | cmin | cmax | id | cd 
------+------+------+------+----+----
 1878 |    0 |    0 |    0 |  1 | 1
 1885 |    0 |    0 |    0 |  3 | 3
 1885 |    0 |    1 |    1 |  4 | 4
 1886 |    0 |    0 |    0 |  5 | xx
 1886 |    0 |    0 |    0 |  6 | xx
 1886 |    0 |    1 |    1 |  2 | 2
(6 rows)

pgsql=# commit;
COMMIT
pgsql=# select xmin,xmax,cmin,cmax,* from tab01;
 xmin | xmax | cmin | cmax | id | cd 
------+------+------+------+----+----
 1878 |    0 |    0 |    0 |  1 | 1
 1885 |    0 |    0 |    0 |  3 | 3
 1885 |    0 |    1 |    1 |  4 | 4
 1886 |    0 |    0 |    0 |  5 | xx
 1886 |    0 |    0 |    0 |  6 | xx
 1886 |    0 |    1 |    1 |  2 | 2
(6 rows)

pgsql=# 
复制代码

 经过反复折腾,终于发现,其实 cmin和 cmax就是一个东西:

看源代码:

复制代码
/* ----------------
 *        heap_getsysattr
 *
 *        Fetch the value of a system attribute for a tuple.
 *
 * This is a support routine for the heap_getattr macro.  The macro
 * has already determined that the attnum refers to a system attribute.
 * ----------------
 */
Datum
heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
{
    Datum        result;

    Assert(tup);

    /* Currently, no sys attribute ever reads as NULL. */
    *isnull = false;

    switch (attnum)
    {
        case SelfItemPointerAttributeNumber:
            /* pass-by-reference datatype */
            result = PointerGetDatum(&(tup->t_self));
            break;
        case ObjectIdAttributeNumber:
            result = ObjectIdGetDatum(HeapTupleGetOid(tup));
            break;
        case MinTransactionIdAttributeNumber:
            result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
            break;
        case MaxTransactionIdAttributeNumber:
            result = TransactionIdGetDatum(HeapTupleHeaderGetXmax(tup->t_data));
            break;
        case MinCommandIdAttributeNumber:
        case MaxCommandIdAttributeNumber:

            /*
             * cmin and cmax are now both aliases for the same field, which
             * can in fact also be a combo command id.    XXX perhaps we should
             * return the "real" cmin or cmax if possible, that is if we are
             * inside the originating transaction?
             */
            result = CommandIdGetDatum(HeapTupleHeaderGetRawCommandId(tup->t_data));
            break;
        case TableOidAttributeNumber:
            result = ObjectIdGetDatum(tup->t_tableOid);
            break;
        default:
            elog(ERROR, "invalid attnum: %d", attnum);
            result = 0;            /* keep compiler quiet */
            break;
    }
    return result;
}
复制代码
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
存储 SQL 关系型数据库
PostgreSQL系统字段cmin和cmax详解
1.cmin和cmax是什么 PG中每个表都包含了一些系统字段,其中包括cmin和cmax。 cmin:插入该元组的命令在插入事务中的命令标识(从0开始累加) cmax:删除该元组的命令在插入事务中的命令标识(从0开始累加) 可以在Select命令的输出列表中显式地指定系统字段。
2941 0
|
关系型数据库 分布式数据库 PolarDB
|
关系型数据库 分布式数据库 定位技术
PolarDB for PostgreSQL 开源必读手册-VACUUM处理(中)
PolarDB for PostgreSQL 开源必读手册-VACUUM处理
168 0
|
关系型数据库 分布式数据库 PolarDB
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
364 0
|
存储 缓存 关系型数据库
|
存储 SQL 并行计算
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍(中)
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍
419 0
|
存储 算法 安全
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍(下)
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍
383 0
|
关系型数据库 分布式数据库 开发工具
|
存储 关系型数据库 Linux
PolarDB for PostgreSQL 开源必读手册-PolarDB安装与配置(下)
PolarDB for PostgreSQL 开源必读手册-PolarDB安装与配置
699 0
下一篇
无影云桌面