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

MogDB工具之数据拯救

原创 多米爸比 2022-03-09
862

一些场景下数据库可能无法正常连接,没有其它恢复手段的情形下,我们可以使用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

后续的恢复过程可以参考测试一。

最后修改时间:2022-08-15 17:46:23
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论