暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PG中的oid和relfilenode之间的关系

yanzongshuaiDBA 2021-03-18
1361

PG中的oid和relfilenode之间的关系


PG中的表由一个relfilenode值,即磁盘上表的文件名(除了外表和分区表)。通常情况下可以在Pg_class表找到这个值,然而也会查考一些表的relfilenode为0.本文介绍这些表relfilenode的内部处理流程。

普通表的relfilenode

PG中创建一个表后,会在系统被pg_class存储它的relfilenode值。下面例子,表创建后,OID和relfilenode都时16808。还可以在磁盘上看到16808文件。

postgres=# create table t2(i int);

CREATE TABLE

postgres=# select oid,relname,relfilenode frompg_class where relname = 't2';

 oid  | relname | relfilenode

-------+---------+-------------

 16808 |t2      |       16808

(1 row)


postgres=# \q

movead@movead-PC:/h2/pgpgpg/bin$ ll../data/base/12835/16808

-rw-------+ 1 movead movead 0 12 31 17:11../data/base/12835/16808

movead@movead-PC:/h2/pgpgpg/bin$

执行truncate、vacuum full等操作后,表数据被重写,并且表文件的relfilenode也会改变。下面测试显示了truncate后,t2的relfilenode值由16808变成16811.

postgres=# truncate t2;
TRUNCATE TABLE
postgres=# select oid,relname,relfilenode from pg_class where relname = 't2';
  oid  | relname | relfilenode
-------+---------+-------------
 16808 | t2      |       16811
(1 row)
postgres=# checkpoint;
CHECKPOINT
postgres=# \q
movead@movead-PC:/h2/pgpgpg/bin$ ll ../data/base/12835/16808
ls: 无法访问'../data/base/12835/16808': 没有那个文件或目录
movead@movead-PC:/h2/pgpgpg/bin$ ll ../data/base/12835/16811
-rw-------+ 1 movead movead 0 12月 31 17:16 ../data/base/12835/16811
movead@movead-PC:/h2/pgpgpg/bin$

nail表的relfilenode

postgres=# select oid, relname, relfilenode,reltablespace
from pg_class
where relfilenode = 0 and relkind = 'r'
order by reltablespace;
 oid  |        relname        | relfilenode | reltablespace
------+-----------------------+-------------+---------------
 1247 | pg_type               |           0 |             0
 1255 | pg_proc               |           0 |             0
 1249 | pg_attribute          |           0 |             0
 1259 | pg_class              |           0 |             0
 3592 | pg_shseclabel         |           0 |          1664
 1262 | pg_database           |           0 |          1664
 2964 | pg_db_role_setting    |           0 |          1664
 1213 | pg_tablespace         |           0 |          1664
 1261 | pg_auth_members       |           0 |          1664
 1214 | pg_shdepend           |           0 |          1664
 2396 | pg_shdescription      |           0 |          1664
 1260 | pg_authid             |           0 |          1664
 6000 | pg_replication_origin |           0 |          1664
 6100 | pg_subscription       |           0 |          1664
(14 rows)
postgres=#

上面的例子的查询可看到这些表的relfilenode都是0.pg_type、pg_proc、pg_attribute和pg_class是non-shared表,称为Nail表。剩余的表是pg_global表空间的shared表。

Pg_class表中的relfilenode字段告诉我们磁盘上存储的文件名是什么。例如在表t2上进行查询时,首先需要从pg_class中获取relfilenode,然后在磁盘上找到对于文件,接着才能进行打开和扫描。如果想查询磁盘上pg_class的文件名,那去哪里找relfilenode呢?有一系列函数提供了转换oid\relfilenode的函数。

postgres=# select pg_relation_filenode(1259);
 pg_relation_filenode
----------------------
                16475
(1 row)
postgres=# select pg_filenode_relation(0,16475);
 pg_filenode_relation
----------------------
 pg_class
(1 row)
postgres=# select pg_filenode_relation(0,16475)::oid;
 pg_filenode_relation
----------------------
                 1259
(1 row)
postgres=#

通过调用pg_relation_filenode(),oid可以转换成relfilenode;通过pg_filenode_relation()函数可以将relfilenode转换成oid。

Shared和nail表的oid和relfilenode之间的关系没有存储在pg_class表,PG如何存储这个映射关系呢?


Nail表的relfilenode存储机制

经过研究后,找到要给pg_filenode.map文件:

movead@movead-PC:/h2/pgpgpg/data/base/12835$ ll pg_filenode.map
-rw-------+ 1 movead movead 512 12 31 15:10 pg_filenode.map
movead@movead-PC:/h2/pgpgpg/data/base/12835$
movead@movead-PC:/h2/pgpgpg/data/global$ ll pg_filenode.map
-rw-------+ 1 movead movead 512 12 31 15:10 pg_filenode.map
movead@movead-PC:/h2/pgpgpg/data/global$

shared表的oid和relfilenode映射关系存储在global目录的pg_filenode.map中。Database为12835的nail表映射关系存储在12835目录的pg_filenode.map中。该文件存储的内容结构是:

typedef struct RelMapping
{
    Oid         mapoid;         /* OID of a catalog */
    Oid         mapfilenode;    /* its filenode number */
} RelMapping;
typedef struct RelMapFile
{
    int32       magic;          /* always RELMAPPER_FILEMAGIC */
    int32       num_mappings;   /* number of valid RelMapping entries */
    RelMapping  mappings[MAX_MAPPINGS];
    pg_crc32c   crc;            /* CRC of all above */
    int32       pad;            /* to make the struct size be 512 exactly */
} RelMapFile;

总结

本文主要介绍了PG的oid和relfilenode的两种表现方式,pg_relation_filenode()获取的值永远是正确的,但是从系统表中查询出的就可能是错误的。

原文

https://www.highgo.ca/2021/01/12/the-mapping-of-oid-and-relfilenode-in-pg/

文章转载自yanzongshuaiDBA,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论