網(wǎng)站首頁 編程語言 正文
今天在網(wǎng)上看到有人問誤刪pg_filenode.map該如何恢復(fù)或者重建,解決這個問題前我們先來了解下pg_filenode.map文件。
對于PostgreSQL中的每張表在磁盤上都有與之相關(guān)的文件,而這些文件的名字便是relfilenode,我們可以通過pg_class的relfilenode字段去查詢。
但是有一部分特殊的表我們會發(fā)現(xiàn)其對應(yīng)的該字段為0,官方文檔的解釋為:0表示這是一個“映射”關(guān)系,其磁盤文件名取決于低層狀態(tài)。那么哪些表的relfilenode字段會是0呢?這些relfilenode為0的表對應(yīng)的文件又該如何去查找呢?
我們都知道對于一張普通表,其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便會發(fā)生變化:
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字段我們也可以發(fā)現(xiàn)分為兩類:一類是pg_type、pg_attribute、pg_proc和pg_class,它們是非共享的表,在內(nèi)核中我們稱為Nail表。而另一類則是reltablespace為1664的,即在pg_global表空間里的共享表。
而為什么這些系統(tǒng)表的relfilenode為0呢?因為對于這種訪問十分頻繁的系統(tǒng)表,我們不希望每次都是從一些其它的系統(tǒng)表去查詢,這樣性能便會非常低,它們便是通過pg_filenode.map文件去進行管理的。
在pg_filenode.map文件中,將這些系統(tǒng)表的oid與relfileno做映射,而這個文件的大小為512,剛好是一個OS disk sector的大小。同時PG做了對齊處理,在源碼上用RelMapFile結(jié)構(gòu)體與之對應(yīng)。結(jié)構(gòu)體大小為:628+44=496+16=512。也就是說這個文件最多存放62條系統(tǒng)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;
接著我們來具體看看這個文件里面存放的內(nèi)容是什么樣的:
如上圖所示,可以將該文件分為四個部分。
第一部分:2717 0059,表示文件頭魔法數(shù)據(jù)字。
#define RELMAPPER_FILEMAGIC0x592717/* version ID value */
第二部分:0011 0000,表示文件中包含的映射對象數(shù)。我們可以通過以下SQL驗證:
剛好是17行數(shù)據(jù),和前面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,這一類便是實際的映射關(guān)系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文件我們來回答前面的問題,如果誤刪了該文件怎么辦呢?
如果該文件某個數(shù)據(jù)庫下的該文件刪除,那么該庫便無法連接:
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文件損壞或者被誤刪后,那么至少對應(yīng)的庫肯定是連接不上了,那么我們也沒辦法手工去創(chuàng)建該文件了。
不過一般來說大部分庫的這個文件都是一樣的,很少會去對該文件進行修改,除非你對這些系統(tǒng)表進行了vacuum full之類的操作。而如果你真的不幸該庫做過類似操作那該怎么辦呢?只好先從其它庫拷貝一個文件過來,然后pg_filedump本庫的pg_class的數(shù)據(jù)文件看看相應(yīng)的系統(tǒng)表的信息,然后要注意,不要去直接修改pg_filenode.map文件,而是要去修改數(shù)據(jù)文件的文件名,讓其滿足pg_filenode.map中的映射關(guān)系。
為什么呢?我們前面說過該文件尾部有一個根據(jù)文件名進行計算的校驗值,如果直接修改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
總結(jié):
誤刪pg_filenode.map怎么辦?首先運氣好的話從別的庫拷貝一個該文件,如果可用的話就可以直接使用。
而如果你的庫上該文件中的系統(tǒng)表做過vacuum full之類的操作,那么便需要通過類似pg_filedump的方式去pg_class的數(shù)據(jù)文件中獲取相關(guān)的信息,然后手動修改相關(guān)數(shù)據(jù)文件名讓其滿足pg_filenode.map中的映射關(guān)系。
當然該方法會很麻煩,所以還是要注意千萬別誤刪了你的pg_filenode.map!
原文鏈接:https://foucus.blog.csdn.net/article/details/122555578
相關(guān)推薦
- 2022-05-26 pandas進行數(shù)據(jù)輸入和輸出的方法詳解_python
- 2022-05-23 C語言的動態(tài)內(nèi)存分配及動態(tài)內(nèi)存分配函數(shù)詳解_C 語言
- 2022-11-15 C++構(gòu)造析構(gòu)賦值運算函數(shù)應(yīng)用詳解_C 語言
- 2022-07-01 Go?數(shù)據(jù)結(jié)構(gòu)之二叉樹詳情_Golang
- 2023-03-29 goland遠程調(diào)試k8s上容器的實現(xiàn)_Golang
- 2024-03-20 SpringBoot使用dynamic-datasource實現(xiàn)多數(shù)據(jù)源方案
- 2023-09-12 git常用指令
- 2021-12-03 Android識別NFC芯片制造商的方法_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支