os: centos 7.4
db: postgresql 10.11

oid、tableoid、ctid、xmin、xmax、cmin、cmax 这些都是 postgresql 数据库表的隐藏列.

起着不同的作用.

版本

# cat /etc/centos-release
CentOS Linux release 7.4.1708 (Core) 
# 
# 
# yum list installed |grep -i postgresql
postgresql10.x86_64                10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-contrib.x86_64        10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-debuginfo.x86_64      10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-devel.x86_64          10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-docs.x86_64           10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-libs.x86_64           10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-odbc.x86_64           12.00.0000-1PGDG.rhel7              @pgdg10  
postgresql10-plperl.x86_64         10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-plpython.x86_64       10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-pltcl.x86_64          10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-server.x86_64         10.11-2PGDG.rhel7                   @pgdg10  
postgresql10-tcl.x86_64            2.4.0-1.rhel7                       @pgdg10  
postgresql10-tcl-debuginfo.x86_64  2.3.1-1.rhel7                       @pgdg10  
postgresql10-test.x86_64           10.11-2PGDG.rhel7                   @pgdg10 

# su - postgres
Last login: Wed Jan 15 18:34:12 CST 2020 on pts/0
$
$
$ psql -c "select version();"
                                                 version                                                  
----------------------------------------------------------------------------------------------------------
 PostgreSQL 10.11 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)

oid、tableoid、ctid

oid 为内部行对象标识符,强烈不建议(或者禁止)用户表使用oid。用户默认建表时 with oids=false
tableoid 行归属的表的oid,通常在有继承关系的父表时,可以快速判断行数据所属的子表。
ctid 标记行的物理位置,格式为 (m,n) 其中 m表示块号,n表示在块内的行号

xmin、xmax、cmin、cmax

多版本实现中控制数据行的可见性

插入行时:xmin 置为当前事务ID,xmax 置为 0
删除行时:xmax 置为当前事务ID
更新行时:旧行上的 xmin 保持不变,旧行上的 xmax 置为当前事务ID
新行上的 xmin 置为当前事务ID,新行上的 xmax 置为 0

cmin、cmax 主要是用于判断同一个事务内的不同命令导致的行版本变化是否可见。这个理解透彻后再补充下

create table 试一下

# su - postgres
$ psql

postgres=# create table tmp_t0 (
  id bigint primary key,
  name varchar(100)
);

postgres=# select oid,relname from pg_class where relname='tmp_t0';
  oid   | relname 
--------+---------
 379767 | tmp_t0
(1 row)

postgres=# select attrelid,attname,attnum from pg_attribute where attrelid=379767;
 attrelid | attname  | attnum 
----------+----------+--------
   379767 | tableoid |     -7
   379767 | cmax     |     -6
   379767 | xmax     |     -5
   379767 | cmin     |     -4
   379767 | xmin     |     -3
   379767 | ctid     |     -1
   379767 | id       |      1
   379767 | name     |      2
(8 rows)

postgres=# insert into tmp_t0 select 1,'a' ;

postgres=# select * from tmp_t0;

 id | name 
----+------
  1 | a
(1 row)

postgres=# select tableoid,cmax,xmax,cmin,xmin,ctid,id,name from tmp_t0;

 tableoid | cmax | xmax | cmin |  xmin  | ctid  | id | name 
----------+------+------+------+--------+-------+----+------
   379767 |    0 |    0 |    0 | 699844 | (0,1) |  1 | a
(1 row)

执行 update

postgres=# begin;

postgres=# update tmp_t0 set name='b' where id=1;

postgres=# select tableoid,cmax,xmax,cmin,xmin,ctid,id,name from tmp_t0;
 tableoid | cmax | xmax | cmin |  xmin  | ctid  | id | name 
----------+------+------+------+--------+-------+----+------
   379767 |    0 |    0 |    0 | 699845 | (0,2) |  1 | b
(1 row)

可以看到新数据的 xmin=699845 ctid=(0,2)

另外一个会话查询数据

postgres=# select tableoid,cmax,xmax,cmin,xmin,ctid,id,name from tmp_t0;
 tableoid | cmax |  xmax  | cmin |  xmin  | ctid  | id | name 
----------+------+--------+------+--------+-------+----+------
   379767 |    0 | 699845 |    0 | 699844 | (0,1) |  1 | a
(1 row)

符合预期

参考:

Logo

一站式 AI 云服务平台

更多推荐