PostgreSQL pg_filenode.map文件介绍

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

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

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

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

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便会发生变化:

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的表:

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的机率。

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,表示文件头魔法数据字。

#define RELMAPPER_FILEMAGIC0x592717/* version ID value */

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

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

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!

到此这篇关于PostgreSQL pg_filenode.map文件介绍的文章就介绍到这了,更多相关PostgreSQL pg_filenode.map内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • PostgreSQL 恢复误删数据的操作

    在Oracle中:删除表或者误删表记录:有个闪回特性,不需要停机操作,可以完美找回记录.当然也有一些其他的恢复工具:例如odu工具,gdul工具.都可以找回数据.而PostgreSQL目前没有闪回特性.如何在不停机情况下恢复误删数据.还好是有完整的热备份. 本文描述的方法是:利用热备份在另一台服务器进行数据恢复:再导入正式环境:这样不影响数据库操作.这方法也适用在Oracle恢复.必须满足几个条件 1.有完整的基础数据文件备份和归档文件备份.所以备份是很重要的. 2.有一台装好同款Postgre

  • PostgreSQL pg_filenode.map文件介绍

    今天在网上看到有人问误删pg_filenode.map该如何恢复或者重建,解决这个问题前我们先来了解下pg_filenode.map文件. 对于PostgreSQL中的每张表在磁盘上都有与之相关的文件,而这些文件的名字便是relfilenode,我们可以通过pg_class的relfilenode字段去查询. 但是有一部分特殊的表我们会发现其对应的该字段为0,官方文档的解释为:0表示这是一个“映射”关系,其磁盘文件名取决于低层状态.那么哪些表的relfilenode字段会是0呢?这些relfil

  • webpack将js打包后的map文件详解

    类似于这样的map文件 由webpack自动生成 参数: devtool: '#eval-source-map',//映射js到原文件 由于打包后的js调试不方面,所以应用此,自动映射报错到原文件 还是很有用的 同样的css设置如下 { test: /\.css$/, loader: 'style-loader!css-loader?sourceMap' } 以上这篇webpack将js打包后的map文件详解是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们. 您可能感兴

  • Vue打包后出现一些map文件的解决方法

    Vue打包后出现一些map文件的解决办法: 问题: 可能很多人在做vue项目打包,打包之后js中,会自动生成一些map文件,那我们怎么把它去掉不要呢? 1,运行  cnpm run build  开始打包 2,会在项目目录下自动创建dist目录,打包好的文件都在其中 解决办法:去src/config/index.js中改一个参数: productionSourceMap:false 把这个改为false.不然在最终打包的文件中会出现一些map文件,map文件的作用在于:项目打包后,代码都是经过压

  • 浅谈Linux环境变量文件介绍

    在Linux系统中,环境变量按照其作用范围不同大致可以分为系统级环境变量和用户级环境变量. 系统级环境变量:每一个登录到系统的用户都能够读取到系统级的环境变量 用户级环境变量:每一个登录到系统的用户只能够读取属于自己的用户级的环境变量 自然而然地,环境变量的配置文件也相应的被分成了系统级和用户级两种. 系统级 /etc/profile 在系统启动后第一个用户登录时运行,并从/etc/profile.d目录的配置文件中搜集shell的设置,使用该文件配置的环境变量将应用于登录到系统的每一个用户.

  • golang语言map全方位介绍

    目录 一.map 1.基本介绍 2.声明基本语法 二.map 的使用 2.map[string]map[string]string使用案例 三.map 的增删改查操作 1.map 增加和更新 2.map 删除 3.map 查找 四.map的其他操作 1.map 遍历: 2.map 的长度 3.map 切片 4.map 排序 五.map 使用细节 总结 一.map 1.基本介绍 map 是 key-value 数据结构,又称为字段或者关联数组.类似其它编程语言的集合, 在编程中是经常使用到 2.声

  • PostgreSQL工具pgAdmin的介绍及使用

    目录 1. pgAdmin的介绍 2. pgAdmin的使用 1. pgAdmin的介绍 pgAdmin 4是一款专门针对PostgreSQL数据库的客户端管理软件,该版本在pgAdmin 3的基础上做了较大的架构变化,由之前的CS架构变更为基于浏览器的BS架构. 2019年1月10日,pgAdmin全球开发组在其官网上发布了最新版本pgAdmin 4 v4.0版本.该版本包括超过26个已知bug修复和新特性.新增的特性有: 新的平滑UI设计 允许查询计划下载存储为SVG格式 增加容器部署选项

  • ASP.NET Core中的静态文件介绍

    静态文件(HTML,CSS,图片和Javascript之类的资源)会被ASP.NET Core应用直接提供给客户端. 静态文件通常位于网站根目录(web root) <content-root>/wwwroot文件夹下.通常会把项目的当前目录设置为Content root,这样项目的web root就可以在开发阶段被明确. public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.Create

  • hta文件介绍(编写小程序的好东东)

    总是想用script语言编写一些小程序,以前总是写成html格式的,可每次打开都会有安全提示,今天突然发现了如果保存成hta格式的文件,效果大不一样. 嘿嘿.. HTA是HTML Application的缩写(HTML应用程序),是软件开发的新概念,直接将HTML保存成HTA的格式,就是一个独立的应用软件,与VB.C++等程序语言所设计的软件没什么差别. 下面是一个HTA的例子: 复制代码 代码如下: <!-example1.hta--><html><head><

  • Erlang中的映射组Map详细介绍

    主要是遇到 Map匹配的问题,所以顺便回忆一下 Erlang 中的映射组 Map,在其它语言中被称作 Hash 哈希或者 Dict 字典. Erlang 从 R17 版本开始支持映射组 创建映射组 Erlang 中的映射组用结构 #{} 表示,创建一个映射组可以这样 复制代码 代码如下: % 不管你怎么排序,最终结果都是按键的字典顺序排列的 #{ name => "wittyfox", age => 19 }. % => #{age => 20,name =&g

  • PowerShell脚本写的文件.ps1文件介绍

    .ps1文件是PowerShell写好的脚本文件.在Windows系统中,默认情况下是不允许执行.ps1文件的,那么怎么才能让系统允许执行.ps1文件呢? 什么是".ps1"文件? 这个是PowerShell写的脚本文本,你可以在记事本中写一段PowerShell代码,然后将其保存为"xxx.ps1",后面要使用它的时候,双击即可运行了.这有点像批处理的".bat"文件,也有点像VBScript的".vbs"文件.这些都是Wi

随机推荐