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是一个从PostgreSQL继承的非并行应用。除此之外,有些情况下还需要从ETL过程备份原始数据。用户可以根据自己的实际场景选择适当的备份/恢复方法。
用户可以在HAWQ中使用gpfdist或PXF执行并行备份,将数据卸载到外部表中。备份文件可以存储在本地文件系统或HDFS上。恢复表的过程就是简单将数据从外部表装载回数据库。
(1)备份步骤
执行以下步骤并行备份:
注意:将所有表的insert语句放在一个单独的事务中,以避免因在备份期间执行任何更新操作而产生问题。
(2)恢复步骤
执行以下步骤从备份还原:
(3)gpfdist与PXF的区别
gpfdist与PXF的区别体现在以下方面:
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
大多数情况使用gpfdist或PXF并行备份能够很好地工作。但以下两种情况不能执行并行备份与还原操作:
在这些情况下,用户可以使用在ETL处理期间生成原始数据的备份,并装载到HAWQ。ETL程序提供了选择在本地还是HDFS存储备份文件的灵活性。
表1汇总了上面讨论的四种备份方法的区别。
gpfdist | PXF | pg_dump | 原始数据备份 | |
---|---|---|---|---|
并行执行 | Yes | Yes | No | No |
增量备份 | No | No | No | Yes |
备份文件存储位置 | 本地文件系统 | HDFS | 本地文件系统 | 本地文件系统, HDFS |
备份文件格式 | Text,CSV | Text,CSV,自定义格式 | Text,Tar,自定义格式 | 依赖原始数据的格式 |
压缩 | No | Yes | 只支持自定义格式 | 可选 |
可伸缩性 | 好 | 好 | — | 好 |
性能 | 装载快速, 卸载快速 | 装载快速, 卸载一般 | — | 快(只拷贝文件) |
表1
在备份数据库前,需要确认有足够的空间存储备份文件。下面说明如何获取数据库大小和估算备份文件所需空间。
(1)使用hawq_toolkit查询需要备份的数据库大小。
gpadmin=# SELECT sodddatsize FROM hawq_toolkit.hawq_size_of_database WHERE sodddatname='db1';
sodddatsize
-------------
16063436
(1 row)
如果数据库中的表是压缩的,此查询显示压缩后的数据库大小。
(2)估算备份文件总大小
(3)得出空间需求
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排错
$ wget http://gpfdist_hostname:port/filenam
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;