HAWQ 技术解析(十五) —— 备份恢复

本文介绍了HAWQ数据库管理系统中的备份与恢复方法,包括gpfdist、PXF及pg_dump的应用,以及如何应对误操作导致的数据丢失等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、为什么还需要备份

二、备份方法

1. gpfdist 和 PXF

(1)备份步骤

(2)恢复步骤

(3)gpfdist 与 PXF 的区别

2. pg_dump 与 pg_restore

3. 原始数据备份

4. 备份方法对比

5. 估计空间需求

三、备份与恢复示例

1. gpfdist 示例

(1)使用 gpfdist 备份

(2)从 gpfdist 备份还原

(3)gpfdist 排错

2. PXF 示例

(1)使用 PXF 备份

(2)从 PXF 备份还原


一、为什么还需要备份

        HAWQ 作为一个数据库管理系统,备份与恢复是其必备功能之一。HAWQ 的用户数据存储在 HDFS 上,系统表存储在 master 节点主机本地。HDFS 上的每个数据块缺省自带三份副本,而且一个数据块的三份副本不会存储在同一个 DataNode 上,因此一个 DataNode 节点失效不会造成数据丢失。而配置了 HDFS NameNode HA 与 HAWQ master HA 后,NameNode 和 master 的单点故障问题也得到了解决。似乎 HAWQ 没有提供额外备份功能的必要。

        事实上,Hadoop 集群上存储和处理的数据量通常非常大,大到要想做全备份,在时间与空间消耗上都是不可接受的,这也就是 HDFS 的数据块自带副本容错的主要原因。那么说到 HAWQ 在数据库中提供了数据备份功能,个人认为有三方面原因:一是自然地从 PostgreSQL 继承,本身就带备份功能;二是提供了一种少量数据迁移的简便方法,比如把一个小表从生产环境迁移到到测试环境;三是处理人为误操作引起的数据问题,例如误删除一个表时,就可以使用备份进行恢复,将数据丢失最小化。

二、备份方法

        HAWQ 提供以下三个应用程序帮助用户备份数据:

  • gpfdist
  • PXF
  • pg_dump

        gpfdist 与 PXF 是并行数据装载/卸载工具,能提供最佳性能,pg_dump 是一个从 PostgreSQL 继承的非并行应用。除此之外,有些情况下还需要从 ETL 过程备份原始数据。用户可以根据自己的实际场景选择适当的备份/恢复方法。

1. gpfdist 和 PXF

        用户可以在 HAWQ 中使用 gpfdist 或 PXF 执行并行备份,将数据卸载到外部表中,备份文件可以存储在本地文件系统或 HDFS 上。恢复表的过程就是简单将数据从外部表装载回数据库。

(1)备份步骤

        执行以下步骤并行备份:

  1. 检查数据库大小,确认文件系统有足够的空间保存备份文件。
  2. 使用 pg_dump 应用程序导出源数据库的 schema。
  3. 在目标数据库中,为每个需要备份的表创建一个可写的外部表。
  4. 向新创建的外部表中装载表数据。

        注意:将所有表的 insert 语句放在一个单独的事务中,以避免因在备份期间执行任何更新操作而产生问题。

(2)恢复步骤

        执行以下步骤从备份还原:

  1. 创建一个数据库用于恢复。
  2. 从 schema 文件(在 pg_dump 过程中被创建)重建 schema。
  3. 为数据库中的每个表建立一个可读的外部表。
  4. 从外部表向实际的表中导入数据。
  5. 装载完成后,运行 ANALYZE 命令,保证基于最新的表统计信息生成优化的查询计划。

(3)gpfdist 与 PXF 的区别

        gpfdist 与 PXF 的区别体现在以下方面:

  • gpfdist 在本地文件系统存储备份文件,PXF 将文件存储在 HDFS 上。
  • gpfdist 只支持平面文本格式,PXF 还支持如 AVRO 的二进制格式,以及用户自定义的格式。
  • gpfdist 不支持生成压缩文件,PXF 支持压缩,用户可以在 Hadoop 中指定使用的压缩算法,如 org.apache.hadoop.io.compress.GzipCodec。
  • gpfdist 和 PXF 都提供快速装载性能,但 gpfdist 要比 PXF 快得多。

2. pg_dump 与 pg_restore

        HAWQ 支持 PostgreSQL 的备份与还原应用程序:pg_dump 和 pg_restore。pg_dump 应用在 master 节点所在主机上创建一个单一的 dump 文件,包含所有注册 segment 的数据,pg_restore 从 pg_dump 创建的备份中还原一个 HAWQ 数据库。大多数情况下,整库备份/还原是不切实际的,因为在 master 节点上没有足够的磁盘空间存储整个分布式数据库的单个备份文件。HAWQ 支持这些应用的主要目的是用于从 PostgreSQL 向 HAWQ 迁移数据。下面是一些 pg_dump 用法的简单示例。

        为数据库 mytest 创建一个备份,导出数据文件格式为 tar:

$ pg_dump -Ft -f mytest.tar mytest

        使用自定义格式创建一个压缩的备份,并且压缩级别为 3:

$ pg_dump -Fc -Z3 -f mytest.dump mytest

        使用 pg_restore 从备份还原:

$ pg_restore -d new_db mytest.dump

3. 原始数据备份

        大多数情况使用 gpfdist 或 PXF 并行备份能够很好地工作,但以下两种情况不能执行并行备份与还原操作:

  • 周期性增量备份。
  • 导出大量数据到外部表,原因是此过程花费的时间太长。

        在这些情况下,用户可以使用在 ETL 处理期间生成原始数据的备份,并装载到 HAWQ。ETL程序提供了选择在本地还是 HDFS 存储备份文件的灵活性。

4. 备份方法对比

        表1 汇总了上面讨论的四种备份方法的区别。

 

gpfdist

PXF

pg_dump

原始数据备份

并行执行

Yes

Yes

No

No

增量备份

No

No

No

Yes

备份文件存储位置

本地文件系统

HDFS

本地文件系统

本地文件系统,HDFS

备份文件格式

Text,CSV

Text,CSV,自定义格式

Text,Tar,自定义格式

依赖原始数据的格式

压缩

No

Yes

只支持自定义格式

可选

可伸缩性

性能

装载快速,卸载快速

装载快速,卸载一般

快(只拷贝文件)

表1

5. 估计空间需求

        在备份数据库前,需要确认有足够的空间存储备份文件。下面说明如何获取数据库大小和估算备份文件所需空间。

(1)使用 hawq_toolkit 查询需要备份的数据库大小。

gpadmin=# SELECT sodddatsize FROM hawq_toolkit.hawq_size_of_database WHERE sodddatname='db1';
 sodddatsize 
-------------
    16063436
(1 row)

        如果数据库中的表是压缩的,此查询显示压缩后的数据库大小。

(2)估算备份文件总大小

  • 如果数据库表和备份文件都是压缩的,可以使用 sodddatsize 作为估算值。
  • 如果数据库表是压缩的,备份文件是非压缩的,需要用 sodddatsize 乘以压缩率。尽管压缩率依赖于压缩算法,但一般可以使用经验值如 300% 进行估算。
  • 如果备份文件是压缩的,数据库表是非压缩的,需要用 sodddatsize 除以压缩率。

(3)得出空间需求

  • 如果使用 PXF 与 HDFS,所需空间为:备份文件大小 * 复制因子。
  • 如果使用 gpfdist,每个 gpfdist 实例的所需空间为:备份文件大小 / gpfdist 实例个数。这是因为表数据将最终分布到所有 gpfdist 实例。

三、备份与恢复示例

1. gpfdist 示例

        gpfdist 是 HAWQ 的并行文件分发程序。hawq load 应用程序操作 gpfdist 可读外部表,将外部表文件并行分发给 HAWQ 处理。当 gpfdist 用于可写外部表时,它并行接收 HAWQ segment 的输出流并写出到一个文件中。

        为了使用 gpfdist,在要还原备份文件的主机上启动 gpfdist 服务器程序,可以在同一个主机或不同主机上启动多个 gpfdist 实例。每个 gpfdist 实例需要指定一个对应目录,gpfdist 从该目录向可读外部表提供文件,或者创建可写外部表的输出文件。例如,如果用户有一台有两块磁盘的专门用于备份的机器,则可以启动两个 gpfdist 实例,每个实例使用使用一块磁盘,如图1 所示:

图1

        也可以在每个 segment 主机上运行 gpfdist 实例,如图2 所示。在备份期间,表数据将最终分布于所有在 CREATE EXTERNAL TABLE 定义的 LOCATION 子句中指定的 gpfdist 实例。

图2

(1)使用 gpfdist 备份

        执行以下步骤,使用 gpfdist 备份 mytest 数据库。

  1. 创建备份位置,并启动 gpfdist 实例。在 hdp4 上启动一个 gpfdist 实例,端口号为 8081,外部数据目录是 /home/gpadmin/mytest_20170223。
    gpfdist -d /home/gpadmin/mytest_20170223 -p 8081 &
    # 如果碰到“cannot open shared object file: No such file or directory”类似的错误,需要先安装相应的依赖包,如:
    gpfdist: error while loading shared libraries: libapr-1.so.0: cannot open shared object file: No such file or directory
    yum install apr
    gpfdist: error while loading shared libraries: libyaml-0.so.2: cannot open shared object file: No such file or directory
    yum install libyaml
  2. 保存 mytest 数据库的 schema。在 HAWQ master 节点所在主机,使用 pg_dump 应用程序,将 mytest 数据库的 schema 保存到文件 mytest.schema。将 schema 文件拷贝到备份目录,用于以后还原数据库 schema。
    pg_dump --schema-only -f mytest.schema mytest
    scp mytest.schema hdp4:/home/gpadmin/mytest_20170223
  3. 为数据库中的每个表创建一个可写的外部表。在 LOCATION 子句中指定 gpfdist 实例。本例使用 CSV 文本格式,但也可以选择其他固定分隔符的文本格式。
    psql mytest
    mytest=# create writable external table wext_base_table (like base_table)
    mytest=# location('gpfdist://hdp4:8081/base_table.csv') format 'csv';
    mytest=# create writable external table wext_t (like t)
    mytest=# location('gpfdist://hdp4:8081/t.csv') format 'csv';
  4. 向外部表卸载数据。所有外部表的数据插入在一个事务中进行。
    mytest=# begin;
    mytest=# insert into wext_base_table select * from base_table;
    mytest=# insert into wext_t select * from t;
    mytest=# commit;
  5. (可选)停止 gpfdist 服务,为其他进程释放端口。下面的命令查找 gpfdist 进程号并杀掉该进程。
    ps -efww|grep gpfdist|grep -v grep|cut -c 9-15|xargs kill -9

(2)从 gpfdist 备份还原

  1. 如果 gpfdist 没运行则启动 gpfdist 实例。下面的命令在 hdp4 上启动一个 gpfdist 实例。
    gpfdist -d /home/gpadmin/mytest_20170223 -p 8081 &
  2. 创建一个新的数据库 mytest2,并将 mytest 的 schema 还原到新库中。
    [gpadmin@hdp3 ~]$ createdb mytest2
    [gpadmin@hdp3 ~]$ scp hdp4:/home/gpadmin/mytest_20170223/mytest.schema .
    [gpadmin@hdp3 ~]$ psql -f mytest.schema -d mytest2
  3. 为每个表创建可读的外部表。
    [gpadmin@hdp3 ~]$ psql mytest2
    mytest2=# create external table rext_base_table (like base_table) location('gpfdist://hdp4:8081/base_table.csv') format 'csv';
    mytest2=# create external table rext_t (like t) location('gpfdist://hdp4:8081/t.csv') format 'csv';
    -- 注意:这里的location子句与前面备份时创建的可写外部表相同。
  4. 从外部表倒回数据。
    mytest2=# insert into base_table select * from rext_base_table;
    mytest2=# insert into t select * from rext_t;
  5. 装载数据后运行 ANALYZE 命令生成表的统计信息。
    mytest2=# analyze base_table;
    mytest2=# analyze t;

(3)gpfdist 排错

  • 确认 HAWQ集 群节点对 gpfdist 可访问。gpfdist 在运行时要被 segment 实例访问,因此必须确保 HAWQ segment 主机可以通过网络访问 gpfdist。由于 gpfdist 程序是一个 web 服务器,可以从 HAWQ 集群的每个主机(master 或 segment 节点)运行类似下面的命令测试连接:
    $ wget http://gpfdist_hostname:port/filename
  • 确认 CREATE EXTERNAL TABLE 定义中提供了 gpfdist 的正确的主机名、端口号和文件名。指定的文件名和路径应该对应 gpfdist 提供的文件(启动 gpfdist 程序时使用的目录路径)。

2. PXF 示例

        HAWQ Extension Framework (PXF)是一个允许 HAWQ 查询外部系统数据的扩展框架。

(1)使用 PXF 备份

        执行以下步骤,使用 PXF 备份 mytest 数据库。

  1. 在 HDFS 上建立一个用作备份的文件夹。
    [root@hdp3 ~]# su - hdfs
    [hdfs@hdp3 ~]$ hdfs dfs -mkdir -p /backup/mytest-2017-02-23
    [hdfs@hdp3 ~]$ hdfs dfs -chown -R gpadmin:gpadmin /backup
  2. 使用 pg_dump 导出数据库 schema,并将 schema 文件存储到备份文件夹中。
    [gpadmin@hdp3 ~]$ pg_dump --schema-only -f mytest.schema mytest
    [gpadmin@hdp3 ~]$ hdfs dfs -copyFromLocal mytest.schema /backup/mytest-2017-02-23
  3. 为数据库的数据库中每个表创建一个可写的外部表。
    [gpadmin@hdp3 ~]$ psql mytest
    mytest=# create writable external table wext_base_table (like base_table)
    mytest=# location('pxf://hdp1:51200/backup/mytest-2017-02-23/base_table?Profile=HdfsTextSimple&COMPRESSION_CODEC=org.apache.hadoop.io.compress.SnappyCodec')
    mytest=# format 'text';
    
    mytest=# create writable external table wext_t (like t)
    mytest=# location('pxf://hdp1:51200/backup/mytest-2017-02-23/t?Profile=HdfsTextSimple&COMPRESSION_CODEC=org.apache.hadoop.io.compress.SnappyCodec')
    mytest=# format 'text';

    这里,所有 base_table 表的备份文件存储在 /backup/mytest-2017-02-23/base_table 文件夹中,所有 t 表的备份文件存储在 /backup/mytest-2017-02-23/t 文件夹中。外部数据文件使用 snappy 压缩保存到磁盘。

  4. 向外部表卸载数据。
    mytest=# begin;
    mytest=# insert into wext_base_table select * from base_table;
    mytest=# insert into wext_t select * from t;
    mytest=# commit;

    外部表使用 snappy 压缩时可能遇到如下错误:

    mytest=# insert into wext_t select * from t;
    ERROR:  remote component error (500) from '172.16.1.125:51200':  type  Exception report   message   native snappy 
    library not available: this version of libhadoop was built without snappy support.    description   The server 
    encountered an internal error that prevented it from fulfilling this request.    exception   
    java.lang.RuntimeException: native snappy library not available: this version of libhadoop was built without 
    snappy support. (libchurl.c:897)  (seg0 hdp4:40000 pid=8565) (dispatcher.c:1801)

    使用下面的方法解决该问题(参考“https://issues.apache.org/jira/browse/HAWQ-951”):

    # 创建目录和软连接
    mkdir -p /usr/lib/hadoop/lib && cd /usr/lib/hadoop/lib && ln -s /usr/hdp/current/hadoop-client/lib/native native
    # 添加pxf-public-classpath属性
    登录 ambari,在Services -> PXF -> Configs -> Advanced pxf-public-classpath 中添加一行:/usr/hdp/current/hadoop-client/lib/snappy*.jar
  5. (可选)改变备份文件夹的 HDFS 文件复制因子。缺省 HDFS 每个数据块复制三份以提供可靠性,根据需要,可以为备份文件降低这个数,以下命令将复制因子设置为 2:
    su - pxf
    -bash-4.1$ hdfs dfs -setrep 2 /backup/mytest-2017-02-23

    注意:这只改变已经存在的文件的备份因子,新文件仍然使用缺省的备份因子。

(2)从 PXF 备份还原

  1. 创建一个新的数据库并还原 schema。
    [gpadmin@hdp3 ~]$ createdb mytest3
    [gpadmin@hdp3 ~]$ hdfs dfs -copyToLocal /backup/mytest-2017-02-23/mytest.schema .
    [gpadmin@hdp3 ~]$ psql -f mytest.schema -d mytest3
  2. 为每个需要还原的表创建一个可读外部表。
    [gpadmin@hdp3 ~]$ psql mytest3
    mytest3=# create external table rext_base_table (like base_table)
    mytest3=# location('pxf://hdp1:51200/backup/mytest-2017-02-23/base_table?Profile=HdfsTextSimple')
    mytest3=# format 'text';
    
    mytest3=# create external table rext_t (like t)
    mytest3=# location('pxf://hdp1:51200/backup/mytest-2017-02-23/t?Profile=HdfsTextSimple')
    mytest3=# format 'text';

    除了不需要指定 COMPRESSION_CODEC,location 子句与前面创建可写外部表的相同,PXF 会自动检测压缩算法。

  3. 从外部表装载数据。
    mytest3=# insert into base_table select * from rext_base_table;
    mytest3=# insert into t select * from rext_t;
  4. 导入数据后运行 ANALYZE。
    mytest3=# analyze base_table;
    mytest3=# analyze t;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值