广告位联系
返回顶部
分享到

PostgreSQL pg_filenode.map文件介绍

PostgreSQL 来源:互联网 作者:佚名 发布时间:2022-09-18 19:44:45 人浏览
摘要

今天在网上看到有人问误删pg_filenode.map该如何恢复或者重建,解决这个问题前我们先来了解下pg_filenode.map文件。 对于PostgreSQL中的每张表在磁盘上都有与之相关的文件,而这些文件的名

今天在网上看到有人问误删pg_filenode.map该如何恢复或者重建,解决这个问题前我们先来了解下pg_filenode.map文件。

对于PostgreSQL中的每张表在磁盘上都有与之相关的文件,而这些文件的名字便是relfilenode,我们可以通过pg_class的relfilenode字段去查询。

但是有一部分特殊的表我们会发现其对应的该字段为0,官方文档的解释为:0表示这是一个“映射”关系,其磁盘文件名取决于低层状态。那么哪些表的relfilenode字段会是0呢?这些relfilenode为0的表对应的文件又该如何去查找呢?

我们都知道对于一张普通表,其relfilenode和oid默认是一样的,例如:

1

2

3

4

5

6

7

bill=# create table t(id int);

CREATE TABLE

bill=# select oid,relname,relfilenode from pg_class where relname = 't';

  oid  | relname | relfilenode

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

 24919 | t       |       24919

(1 row)

但是当我们对该表进行了例如vacuum full、truncate之类的操作后,那么relfilenode便会发生变化:

1

2

3

4

5

6

7

bill=# vacuum FULL t;

VACUUM

bill=# select oid,relname,relfilenode from pg_class where relname = 't';

  oid  | relname | relfilenode

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

 24919 | t       |       24922

(1 row)

那么我们再来看看那些relfilenode为0的表:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

bill=# select oid, relname, relfilenode,reltablespace

bill-# from pg_class

bill-# where relfilenode = 0 and relkind = 'r'

bill-# order by reltablespace;

 oid  |        relname        | relfilenode | reltablespace

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

 1247 | pg_type               |           0 |             0

 1249 | pg_attribute          |           0 |             0

 1255 | pg_proc               |           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

 6100 | pg_subscription       |           0 |          1664

 6000 | pg_replication_origin |           0 |          1664

(14 rows)

这些表通过reltablespace字段我们也可以发现分为两类:一类是pg_type、pg_attribute、pg_proc和pg_class,它们是非共享的表,在内核中我们称为Nail表。而另一类则是reltablespace为1664的,即在pg_global表空间里的共享表。

而为什么这些系统表的relfilenode为0呢?因为对于这种访问十分频繁的系统表,我们不希望每次都是从一些其它的系统表去查询,这样性能便会非常低,它们便是通过pg_filenode.map文件去进行管理的。

在pg_filenode.map文件中,将这些系统表的oid与relfileno做映射,而这个文件的大小为512,刚好是一个OS disk sector的大小。同时PG做了对齐处理,在源码上用RelMapFile结构体与之对应。结构体大小为:628+44=496+16=512。也就是说这个文件最多存放62条系统catalog表的记录。

由于这个文件的重要性,刚好与disk sector大小对齐,减少文件crash的机率。

1

2

3

4

5

6

7

8

9

10

11

12

13

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;

接着我们来具体看看这个文件里面存放的内容是什么样的:

如上图所示,可以将该文件分为四个部分。

第一部分:2717 0059,表示文件头魔法数据字。

1

#define RELMAPPER_FILEMAGIC0x592717/* version ID value */

第二部分:0011 0000,表示文件中包含的映射对象数。我们可以通过以下SQL验证:

刚好是17行数据,和前面0011一致。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

bill=# select relname,relfilenode from pg_class where pg_relation_filepath(oid) like 'base/16385/%' and relfilenode = 0;

              relname              | relfilenode

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

 pg_toast_1255                     |           0

 pg_toast_1255_index               |           0

 pg_proc_oid_index                 |           0

 pg_proc_proname_args_nsp_index    |           0

 pg_type_oid_index                 |           0

 pg_type_typname_nsp_index         |           0

 pg_attribute_relid_attnam_index   |           0

 pg_attribute_relid_attnum_index   |           0

 pg_class_oid_index                |           0

 pg_class_relname_nsp_index        |           0

 pg_class_tblspc_relfilenode_index |           0

 pg_attribute                      |           0

 pg_proc                           |           0

 pg_type                           |           0

 pg_toast_1247                     |           0

 pg_toast_1247_index               |           0

 pg_class                          |           0

(17 rows)

第三部分:04eb 0000 4095 0000,这一类便是实际的映射关系04eb即对象的oid,4095表示对象的relfilenode。

第四部分:ebfa f3a4,文件尾的校验值,通过crc32算法对文件名计算得出:

/* verify the CRC */

INIT_CRC32C(crc);

COMP_CRC32C(crc, (char *) map, offsetof(RelMapFile, crc));

FIN_CRC32C(crc);

if (!EQ_CRC32C(crc, map->crc))

ereport(FATAL,

(errmsg(“relation mapping file “%s” contains incorrect checksum”,

mapfilename)));

介绍完pg_filenode.map文件我们来回答前面的问题,如果误删了该文件怎么办呢?

如果该文件某个数据库下的该文件删除,那么该库便无法连接:

pg14@vm-192-168-204-153-> psql bill bill

psql: error: connection to server on socket “/home/pg14/pgdata/.s.PGSQL.2022” failed: FATAL: could not open file “base/16385/pg_filenode.map”: No such file or directory

但是不会影响其它库的连接:

pg14@vm-192-168-204-153-> psql postgres

psql (14.1)

Type “help” for help.

postgres=#

而如果global目录下的该文件误删,那么所有库均无法连接:

pg14@vm-192-168-204-153-> psql postgres

psql: error: connection to server on socket “/home/pg14/pgdata/.s.PGSQL.2022” failed: FATAL: could not open file “global/pg_filenode.map”: No such file or directory

pg14@vm-192-168-204-153-> psql bill

psql: error: connection to server on socket “/home/pg14/pgdata/.s.PGSQL.2022” failed: FATAL: could not open file “global/pg_filenode.map”: No such file or directory

因此我们可以知道,当pg_filenode.map文件损坏或者被误删后,那么至少对应的库肯定是连接不上了,那么我们也没办法手工去创建该文件了。

不过一般来说大部分库的这个文件都是一样的,很少会去对该文件进行修改,除非你对这些系统表进行了vacuum full之类的操作。而如果你真的不幸该库做过类似操作那该怎么办呢?只好先从其它库拷贝一个文件过来,然后pg_filedump本库的pg_class的数据文件看看相应的系统表的信息,然后要注意,不要去直接修改pg_filenode.map文件,而是要去修改数据文件的文件名,让其满足pg_filenode.map中的映射关系。

为什么呢?我们前面说过该文件尾部有一个根据文件名进行计算的校验值,如果直接修改pg_filenode.map文件的话,则会提示校验值不对:

psql: error: connection to server on socket “/home/pg14/pgdata/.s.PGSQL.2022” failed: FATAL: relation mapping file “base/16385/pg_filenode.map” contains incorrect checksum

总结:

误删pg_filenode.map怎么办?首先运气好的话从别的库拷贝一个该文件,如果可用的话就可以直接使用。

而如果你的库上该文件中的系统表做过vacuum full之类的操作,那么便需要通过类似pg_filedump的方式去pg_class的数据文件中获取相关的信息,然后手动修改相关数据文件名让其满足pg_filenode.map中的映射关系。

当然该方法会很麻烦,所以还是要注意千万别误删了你的pg_filenode.map!


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://foucus.blog.csdn.net/article/details/122555578
相关文章
  • Postgresql删除数据库表中重复数据的几种方法
    一直使用Postgresql数据库,有一张表是这样的: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 DROP TABLE IF EXISTS public.devicedata; CREATE TABLE public.devicedata ( Id varchar(20
  • PostgreSQL HOT与PHOT有哪些区别

    PostgreSQL HOT与PHOT有哪些区别
    1、HOT概述 PostgreSQL中,由于其多版本的特性,当我们进行数据更新时,实际上并不是直接修改元数据,而是通过新插入一行数据来进行间接
  • PostgreSQL索引失效会发生什么?

    PostgreSQL索引失效会发生什么?
    前段时间碰到个奇怪的索引失效的问题,实际情况类似下面这样: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 bill=# begin; BEGIN bill=*# create inde
  • PostgreSQL pg_filenode.map文件介绍

    PostgreSQL pg_filenode.map文件介绍
    今天在网上看到有人问误删pg_filenode.map该如何恢复或者重建,解决这个问题前我们先来了解下pg_filenode.map文件。 对于PostgreSQL中的每张表在磁
  • PostgreSQL limit的神奇作用介绍
    最近碰到这样一个SQL引发的性能问题,SQL内容大致如下: 1 2 3 4 5 6 7 SELECT * FROM t1 WHERE id = 999 AND (case $1 WHEN true THEN info = $2 ELSE info = $3 end) l
  • PostgreSql生产级别数据库安装要注意事项

    PostgreSql生产级别数据库安装要注意事项
    我让公司的小伙伴写一个生产级别的PostgreSQL的安装文档,结果他和我说:不是用一个命令就能安装好么?还用写文档么?。我知道他想说的
  • PostgreSQL12.5中分区表的一些操作介绍
    1、创建一个有DEFAULT的分区表 1、先创建主表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 create table tbl_log ( id serial, create_time timestamp(0) without time zone, remark char
  • Postgres中UPDATE更新语句源码分析
    PG中UPDATE源码分析 本文主要描述SQL中UPDATE语句的源码分析,代码为PG13.3版本。 整体流程分析 以update dtea set id = 1;这条最简单的Update语句进行
  • 在Centos8-stream安装PostgreSQL13的教程

    在Centos8-stream安装PostgreSQL13的教程
    一、安装postgresql13-server 1 2 yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm yum install -y postgresql13-
  • PostgreSQL自动更新时间戳实例介绍
    什么是PostgreSQL时间戳数据类型? 在PostgreSQL中,下一个数据类型是 TIMESTAMP ,它可以存储 TIME 和 DATE 值。但它不支持任何 时区数据。这意味
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计