postgresql 的系统列 oid、tableoid、xmin、cmin、xmax、cmax、

oid
一行的对象标识符(对象ID)。
该列只有在表使用WITH OIDS创建时或者default_with_oids配置变量被设置时才存在。
该列的类型为oid(与列名一致),该类型详见第 8.18 节。

tableoid
包含这一行的表的OID。
该列是特别为从继承层次(见第 5.9 节)中选择的查询而准备,因为如果没有它将很难知道一行来自于哪个表。
tableoid可以与pg_class的oid列进行连接来获得表的名称。

xmin
插入该行版本的事务身份(事务ID)。
一个行版本是一个行的一个特别版本,对一个逻辑行的每一次更新都将创建一个新的行版本。

cmin
插入事务中的命令标识符(从0开始)。

xmax
删除事务的身份(事务ID),对于未删除的行版本为0。
对于一个可见的行版本,该列值也可能为非零。
这通常表示删除事务还没有提交,或者一个删除尝试被回滚。

cmax
删除事务中的命令标识符,或者为0。

ctid
行版本在其表中的物理位置。
注意尽管ctid可以被用来非常快速地定位行版本,但是一个行的ctid会在被更新或者被VACUUM FULL移动时改变。
因此,ctid不能作为一个长期行标识符。OID或者最好是一个用户定义的序列号才应该被用来标识逻辑行。

初始化数据

postgres=# create table tmp_t0(c0 varchar(100),c1 varchar(100));
CREATE TABLE
postgres=# insert into tmp_t0(c0,c1)values('1','1');
INSERT 0 1
postgres=# select tableoid,cmax,xmax,cmin,xmin,ctid,c0,c1,txid_current() from tmp_t0;
 tableoid | cmax | xmax | cmin | xmin | ctid  | c0 | c1 | txid_current 
----------+------+------+------+------+-------+----+----+--------------
    16393 |    0 |    0 |    0 | 1947 | (0,1) | 1  | 1  |         1948
(1 row)
postgres=# insert into tmp_t0(c0,c1)values('2','2');
INSERT 0 1
postgres=# select tableoid,cmax,xmax,cmin,xmin,ctid,c0,c1,txid_current() from tmp_t0;
 tableoid | cmax | xmax | cmin | xmin | ctid  | c0 | c1 | txid_current 
----------+------+------+------+------+-------+----+----+--------------
    16393 |    0 |    0 |    0 | 1947 | (0,1) | 1  | 1  |         1950
    16393 |    0 |    0 |    0 | 1949 | (0,2) | 2  | 2  |         1950
(2 rows)

postgres=#

更新

session 1 操作

postgres=# begin;
BEGIN
postgres=# select tableoid,cmax,xmax,cmin,xmin,ctid,c0,c1,txid_current() from tmp_t0;
 tableoid | cmax | xmax | cmin | xmin | ctid  | c0 | c1 | txid_current 
----------+------+------+------+------+-------+----+----+--------------
    16393 |    0 |    0 |    0 | 1947 | (0,1) | 1  | 1  |         1951
    16393 |    0 |    0 |    0 | 1949 | (0,2) | 2  | 2  |         1951
(2 rows)

postgres=# update tmp_t0 set c1='11' where c0='1';
UPDATE 1
postgres=# select tableoid,cmax,xmax,cmin,xmin,ctid,c0,c1,txid_current() from tmp_t0;
 tableoid | cmax | xmax | cmin | xmin | ctid  | c0 | c1 | txid_current 
----------+------+------+------+------+-------+----+----+--------------
    16393 |    0 |    0 |    0 | 1949 | (0,2) | 2  | 2  |         1951
    16393 |    0 |    0 |    0 | 1951 | (0,3) | 1  | 11 |         1951
(2 rows)

可以看到,update之后 c0='1’的ctid由(0,1)变为(0,3),同时xmin也发生了相应的变化。
此时在 session 1 里不提交。

session 2 查看

postgres=# select tableoid,cmax,xmax,cmin,xmin,ctid,c0,c1,txid_current() from tmp_t0;
 tableoid | cmax | xmax | cmin | xmin | ctid  | c0 | c1 | txid_current 
----------+------+------+------+------+-------+----+----+--------------
    16393 |    0 | 1951 |    0 | 1947 | (0,1) | 1  | 1  |         1953
    16393 |    0 |    0 |    0 | 1949 | (0,2) | 2  | 2  |         1953
(2 rows)

显示的c0='1’为update之前的值。postgresql 默认的事务隔离级别时 read committed,所以在session 2 是无法看到session 1已经更新,但是未提交的数据。

这个也侧面验证了 postgresql 的 mvcc 机制导致没有在行原地 update,而是变为相应的 deleted 标签和插入新行。

参考:
http://postgres.cn/docs/9.6/ddl-system-columns.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据库人生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值