一些场景下数据库可能无法正常连接,没有其它恢复手段的情形下,我们可以使用mog_filedump工具对数据文件进行拯救。
本文将在Centos平台演示mog_filedump工具的使用方法:
mog_filedump工具准备
注意:工具包的下载请参考MogDB插件之跨库访问
将官网下载的toolkits_Centos_x86_2.1.0.tar.gz上传到服务器后,解压
$ tar xvf toolkits_Centos_x86_2.1.0.tar.gz
解压后进入toolkits/mog_filedump/子目录即可使用
$ cd toolkits/mog_filedump
$ ll mog_filedump
-rwx------ 1 omm dbgrp 313536 Jan 7 18:59 mog_filedump
测试一:直接拯救数据
前提条件:已知表结构及数据文件路径
创建测试表
MogDB=> create table foo (x int, y bool, z text, w timestamp);
CREATE TABLE
MogDB=> insert into foo values(135, true, 'test', now());
INSERT 0 1
MogDB=> insert into foo values(789, null, 'enmo', null);
INSERT 0 1
MogDB=> checkpoint;
CHECKPOINT
MogDB=> select relfilenode from pg_class where relname = 'foo';
relfilenode
-------------
82021
(1 rows)
MogDB=> select pg_relation_filepath(82021);
pg_relation_filepath
----------------------
base/15364/82021
(1 row)
上面我们知道测试表foo的表结构及数据文件的存储路径,那我们可以直接使用如下命令来查看数据:
$ ./mog_filedump -D int,bool,text,timestamp /opt/data2100/base/15364/82021 | grep COPY
COPY: 135 t test 2022-03-09 08:30:51.621082
COPY: 789 \N enmo \N
上面通过COPY关键字可以过滤出表的数据,数据是COPY的形式。
下面把数据加工处理到文件,然后可以再导入。
$ ./mog_filedump -D int,bool,text,timestamp /opt/data2100/base/15364/82021 \
| grep COPY \
| perl -lne 's/^COPY: //g; print;' > /home/omm/foo.dat
创建恢复表,并使用COPY命令导入数据
create table foo2 (x int, y bool, z text, w timestamp);
\copy foo2 from '/home/omm/foo.dat'
select * from foo2 ;
查询数据结果如下
x | y | z | w
-----+---+------+----------------------------
135 | t | test | 2022-03-09 08:30:51.621082
789 | | enmo |
(2 rows)
测试二:查询表结构及恢复数据
很多情况下我们可能不知道表结构,只知道表的名称,那我们需要先获取表的字段结构及数据文件路径。
1.获取数据表结构
数据表的字段结构存储在pg_attribute系统表中,数据表的文件路径filenode存储在pg_class系统表中,查看pg_attribute和pg_class这两张系统表的数据文件即可。
获取系统表的数据文件需要知道系统表的filenode,在正常运行的数据库中,我们可以通过以下语句来查看系统表的数据文件路径。
select oid,relname,relfilenode,pg_relation_filepath(oid)
from pg_class
where relfilenode=0
and relkind='r'
and pg_relation_filepath(oid) like 'base_%';
注意:系统表对应的数据文件路径,不同机器环境下看到的最后一列可能会不一样,但前三列信息是一样的。
oid | relname | relfilenode | pg_relation_filepath
------+--------------+-------------+----------------------
1247 | pg_type | 0 | base/15364/14832
1259 | pg_class | 0 | base/15364/14919
1249 | pg_attribute | 0 | base/15364/14901
1255 | pg_proc | 0 | base/15364/14905
7815 | gs_package | 0 | base/15364/14912
(5 rows)
除了可以通过执行语句来获取,还有另外一种方式:系统表的filenode信息虽然没有记录到pg_class中,但记录在每个DB的pg_filenode.map文件里。
$ hexdump /opt/data2100/base/15364/pg_filenode.map
0000000 2718 0059 0014 0000 04eb 0000 3a47 0000
0000010 04e1 0000 3a35 0000 04e7 0000 3a39 0000
0000020 04df 0000 39f0 0000 1e87 0000 3a40 0000
0000030 0b14 0000 3a3b 0000 0b15 0000 3a3d 0000
0000040 1f42 0000 3a42 0000 1f43 0000 3a44 0000
0000050 0a62 0000 3a37 0000 0a63 0000 3a38 0000
0000060 0a66 0000 3a49 0000 0a67 0000 3a4a 0000
0000070 26fd 0000 3a4b 0000 0a82 0000 3a3e 0000
0000080 0a83 0000 3a3f 0000 2709 0000 3a46 0000
0000090 2608 0000 3a45 0000 0a8f 0000 39f2 0000
00000a0 0a90 0000 39f3 0000 0000 0000 0000 0000
00000b0 0000 0000 0000 0000 0000 0000 0000 0000
*
0000ff0 0000 0000 0000 0000 5046 2d9d 0000 0000
0001000
该文件的内容其实不难理解:头部和尾部是版本及校验和信息,中间是20(hex 0014)条系统记录:
04eb(3a47)--1259(14919):pg_class
04e1(3a35)--1249(14901):pg_attribute
04e7(3a39)--1255(14905):pg_proc
04df(39f0)--1247(14832):pg_type
1e87(3a40)--7815(14912):gs_package
0b14(3a3b)--2836(14907):pg_toast_1255
0b15(3a3d)--2837(14909):pg_toast_1255_index
1f42(3a42)--8002(14914):pg_toast_7815
1f43(3a44)--8003(14916):pg_toast_7815_index
0a62(3a37)--2658(14903):pg_attribute_relid_attnam_index
0a63(3a38)--2659(14904):pg_attribute_relid_attnum_index
0a66(3a49)--2662(14921):pg_class_oid_index
0a67(3a4a)--2663(14922):pg_class_relname_nsp_index
26fd(3a4b)--9981(14923):pg_class_tblspc_relfilenode_index
0a82(3a3e)--2690(14910):pg_proc_oid_index
0a83(3a3f)--2691(14911):pg_proc_proname_args_nsp_index
2709(3a46)--9993(14918):gs_package_oid_index
2608(3a45)--9736(14917):gs_package_name_index
0a8f(39f2)--2703(14834):pg_type_oid_index
0a90(39f3)--2704(14835):pg_type_typname_nsp_index
比如上面第一行:04eb(3a47)–1259(14919):pg_class
04eb(3a47)是系统表pg_class的oid与filenode的hex形式,转换成十进制,就是上面查询语句中pg_class的oid=1259,以及base/15364/14919路径最后的部分14919。(15364代表DB)
注意:我们实际环境看到的内容跟上面类似,括号里的值可能有所不同,这与database cluster初始化的环境有关。
再回到主题,根据pg_filenode.map文件,当前环境获取到pg_attribute和pg_class这两张系统表的数据文件路径分别为:
- pg_class base/15364/14919
- pg_attribute base/15364/14901
1.1 获取foo表的文件路径
pg_class的数据文件是base/15364/14919,通过该文件获取foo表的filenode信息。
$ ./mog_filedump -o -D name,oid,oid,oid,oid,oid,oid,~ \
/opt/data2100/base/15364/14919 | grep COPY | grep foo
COPY: foo 73792 82023 0 73790 0 82021
看到第七个字段82021就是foo表的filenode,也就是我们需要的文件路径信息。
1.2 获取foo表的字段结构
pg_attribute的数据文件是base/15364/14901,通过该文件获取foo表的字段结构信息。
$ ./mog_filedump -D oid,name,oid,int,smallint,smallint,~ \
/opt/data2100/base/15364/14901 | \
grep COPY | grep 82021
COPY: 82021 x 23 -1 4 1
COPY: 82021 y 16 -1 1 2
COPY: 82021 z 25 -1 -1 3
COPY: 82021 w 1114 -1 8 4
COPY: 82021 ctid 27 0 6 -1
COPY: 82021 xmin 28 0 8 -3
COPY: 82021 cmin 29 0 4 -4
COPY: 82021 xmax 28 0 8 -5
COPY: 82021 cmax 29 0 4 -6
COPY: 82021 tableoid 26 0 4 -7
COPY: 82021 xc_node_id 23 0 4 -8
前面四个字段是foo表所需的普通字段,后面几个是系统字段无需关注,第三列是字段的类型oid,可以通过pg_type系统表查到对应的数据类型。
oid | typname
------+-----------
16 | bool
23 | int4
25 | text
1114 | timestamp
(4 rows)
按照上面COPY数据最后一列字段顺序,数据类型依次是int4(注意后面要使用标准的int类型)、bool,text,timestamp。
2.获取数据表数据
获取了foo表数据文件路径及字段结构信息,再使用如下命令读取foo表的数据文件。
$ ./mog_filedump -o \
-D int,bool,text,timestamp \
/opt/data2100/base/15364/82021 | grep COPY
注意我们增加了一个-o选项来剔除死元组记录,前面我们插入了两条记录,如果在数据恢复之前第一条记录被delete语句删除,则恢复的数据我们将只看到第二条记录。
COPY: 789 \N enmo \N
后续的恢复过程可以参考测试一。




