系统字段
系统字段
VITO_ch123 发表于1年前
系统字段
  • 发表于 1年前
  • 阅读 10
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 介绍表中存在的系统字段 xmin xmax cmin cmax ctid

postgres建立的表中都有几个系统字段,这些字段是由系统隐含定义的,因此这些名字不能用于用户定义的字段名

oid     行对象标识符,这个字段只有在创建表的时候使用with oids 选项,或者配置 default_with_oids的值为真创建的表才有该字段,其类型为OID。

create table testoid(id int,content text) with oids;
create table test(id int,content text);

postgres=# \d+ testoid 
                        Table "public.testoid"
 Column  |  Type   | Modifiers | Storage  | Stats target | Description 
---------+---------+-----------+----------+--------------+-------------
 id      | integer |           | plain    |              | 
 content | text    |           | extended |              | 
Has OIDs: yes

postgres=# \d+ test
                          Table "public.test"
 Column  |  Type   | Modifiers | Storage  | Stats target | Description 
---------+---------+-----------+----------+--------------+-------------
 id      | integer |           | plain    |              | 
 content | text    |           | extended |              | 

从上面的例子我们可以知道,testoid 为Has OIDs:yes 而表test没有。

  tableoid  包含本行的表的oid,这个字段对那些从继承层次中选取的查询特别有用,因为如果没有他的话,我们很难说明一行来自哪个独立的表, tableoid 可以和pg_class中的oid字段连接起来获取表名。

postgres=# select a.tableoid,b.relname,a.id,a.content from testoid a,pg_class b where a.tableoid=b.oid;
 tableoid |  relname   | id  | content 
----------+------------+-----+---------
    16385 | testoid    |   0 | test0
    16399 | testoid001 |   1 | test1
    16399 | testoid001 |   3 | test3
    16405 | testoid002 | 101 | test101
    16411 | testoid003 | 202 | test202
(5 rows)

上面的例子我们知道数据来自某个表,以及和pg_class 连接知道表名。在分区表查询数据来源的时候很方便。

cmin,cmax

cmin:插入该元组的命令在插入事务中的命令标识(从0开始累加)

cmax:删除该元组的命令在插入事务中的命令标识(从0开始累加)

postgres=# select oid,cmin,cmax,* from testtable;
  oid  | cmin | cmax | id  | content 
-------+------+------+-----+---------
 16733 |    5 |    5 |   2 | test3
 16735 |    5 |    5 |   3 | 3test3
 16736 |    5 |    5 | 101 | test101
 16737 |    5 |    5 | 202 | test202
 16732 |    3 |    3 |   0 | 0test3
 16734 |    5 |    5 |   1 | 1test3

查询出cmin,cmax如上例所示。

xmin,cmax用于判断同一个事物内其他命令导致的行版本是否可见,如果一个事务内的所有命令严格顺序执行,那么每个命令总能看到之前该事务内的所有变更,然而一个事务内的命令交替执行,比如用游标进行查询,fetch游标时看到的是声明游标时候的数据快照而不是fetch执行时,即声明游标后对数据的变更对该游标不可见。

postgres=# begin;
BEGIN
postgres=# insert into testtable values (0,'test0');
INSERT 16739 1
postgres=# select oid,xmin,xmax,cmin,cmax,* from testtable;
  oid  | xmin | xmax | cmin | cmax | id | content 
-------+------+------+------+------+----+---------
 16739 | 1858 |    0 |    0 |    0 |  0 | test0
(1 row)
postgres=# declare tb1_v cursor for select xmin,xmax,cmin,cmax,id,content from  testtable ;
DECLARE CURSOR
postgres=# update testtable  set content ='0test0' where id=0;
UPDATE 1
postgres=# select oid,xmin,xmax,cmin,cmax,* from testtable;
  oid  | xmin | xmax | cmin | cmax | id | content 
-------+------+------+------+------+----+---------
 16739 | 1858 |    0 |    1 |    1 |  0 | 0test0
(1 row)
postgres=# fetch all from tb1_v;
 xmin | xmax | cmin | cmax | id | content 
------+------+------+------+----+---------
 1858 | 1858 |    0 |    0 |  0 | test0
(1 row)

xmin,xmax

xmin: 插入该行版本的事务ID,一个行版本是一行的一个状态。行的每一次更新都为同一个逻辑行创建一个新的行版本。

 xmax: 删除该行版本的事务ID,如果不是被删除的行版本,那么是零,在一个可见行版本里,这个字段有可能是非0,通常这事务还未被提交,或者被回滚掉。

postgres=# insert into testtable values (1,'test1');
INSERT 16740 1
postgres=# select oid,xmin,xmax,cmin,cmax,* from testtable;
  oid  | xmin | xmax | cmin | cmax | id | content 
-------+------+------+------+------+----+---------
 16740 | 1864 |    0 |    0 |    0 |  1 | test1
(1 row)
postgres=# insert into testtable values (2,'test2');
INSERT 16741 1
postgres=# select oid,xmin,xmax,cmin,cmax,* from testtable;
  oid  | xmin | xmax | cmin | cmax | id | content 
-------+------+------+------+------+----+---------
 16740 | 1864 |    0 |    0 |    0 |  1 | test1
 16741 | 1865 |    0 |    0 |    0 |  2 | test2
(2 rows)
--test2插入的id为1865
postgres=# select txid_current();
 txid_current 
--------------
         1866
(1 row)
当前的xmin为1866,那么下一个事务分配的xmin为1866

postgres=# begin ;
BEGIN
postgres=# select oid,xmin,xmax,cmin,cmax,* from testtable;
  oid  | xmin | xmax | cmin | cmax | id | content 
-------+------+------+------+------+----+---------
 16741 | 1865 |    0 |    0 |    0 |  2 | test2
 16740 | 1867 |    0 |    0 |    0 |  1 | 1test1
(2 rows)

postgres=# update testtable set content='1test1' where id=1;
UPDATE 1

postgres=# select oid,xmin,xmax,cmin,cmax,* from testtable;
  oid  | xmin | xmax | cmin | cmax | id | content 
-------+------+------+------+------+----+---------
 16741 | 1865 |    0 |    0 |    0 |  2 | test2
 16740 | 1868 |    0 |    1 |    1 |  1 | 1test1
(2 rows)

当更新一个数据后,xmin更新为1868,重新打开一个session,查看
postgres=# select oid,xmin,xmax,cmin,cmax,* from testtable;
  oid  | xmin | xmax | cmin | cmax | id | content 
-------+------+------+------+------+----+---------
 16741 | 1865 |    0 |    0 |    0 |  2 | test2
 16740 | 1867 | 1868 |    0 |    0 |  1 | 1test1
(2 rows)

xmax为1868代表该事务未提及,如果提交,1867事务会被1868事务修改,xmin变成1868,如果rollback,那么xmax为1868,xmin为1867。
postgres=# rollback ;
ROLLBACK
postgres=# select oid,xmin,xmax,cmin,cmax,* from testtable;
  oid  | xmin | xmax | cmin | cmax | id | content 
-------+------+------+------+------+----+---------
 16741 | 1865 |    0 |    0 |    0 |  2 | test2
 16740 | 1867 | 1868 |    0 |    0 |  1 | 1test1

 ctid 一个行版本在它所处的表内的物理位置,请注意,尽管ctid可以用于非常快速的定位行版本,但是每次vacuum full之后,一个行的ctid都会被更新或者移动,因此ctid不能作为长期的标识符,应该使用oid或者自定义标识符。

注意:

    不要假设oid是跨表唯一的,如果需要全数据库内的标识,请使用tableoid和oid的组合。

共有 人打赏支持
粉丝 2
博文 20
码字总数 68787
×
VITO_ch123
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: