系统字段
2016-07-06 00:00
253 查看
摘要: 介绍表中存在的系统字段 xmin xmax cmin cmax ctid
postgres建立的表中都有几个系统字段,这些字段是由系统隐含定义的,因此这些名字不能用于用户定义的字段名
从上面的例子我们可以知道,testoid 为Has OIDs:yes 而表test没有。
上面的例子我们知道数据来自某个表,以及和pg_class 连接知道表名。在分区表查询数据来源的时候很方便。
查询出cmin,cmax如上例所示。
不要假设oid是跨表唯一的,如果需要全数据库内的标识,请使用tableoid和oid的组合。
postgres建立的表中都有几个系统字段,这些字段是由系统隐含定义的,因此这些名字不能用于用户定义的字段名
oid 行对象标识符,这个字段只有在创建表的时候使用with oids 选项,或者配置 default_with_oids的值为真创建的表才有该字段,其类型为OID。
[code=language-sql]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字段连接起来获取表名。
[code=language-sql]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开始累加)
[code=language-sql]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执行时,即声明游标后对数据的变更对该游标不可见。
[code=language-sql]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,通常这事务还未被提交,或者被回滚掉。
[code=language-sql]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的组合。
相关文章推荐
- PostgreSQL新手入门教程
- PostgreSQL教程(十):性能提升技巧
- PostgreSQL教程(二):模式Schema详解
- PostgreSQL教程(十三):数据库管理详解
- 深入解读PostgreSQL中的序列及其相关函数的用法
- PostgreSQL教程(八):索引详解
- PostgreSQL教程(三):表的继承和分区表详解
- 简单介绍Ruby on Rails对PostgreSQL数组类型的支持
- PostgreSQL教程(十九):SQL语言函数
- PostgreSQL教程(四):数据类型详解
- PostgreSql新手必学入门命令小结
- 用一整天的时间安装postgreSQL NTFS权限
- FREEBSD安装POSTGRESQL笔记
- Mac OS上安装PostgreSQL的教程
- PostgreSQL8.3.3安装方法第1/2页
- 深入理解PostgreSQL的MVCC并发处理方式
- PostgreSQL教程(一):数据表详解
- PostgreSQL教程(十二):角色和权限管理介绍
- PostgreSQL教程(五):函数和操作符详解(1)