目录导航
1. 概述
GBase 数据库当前的备份恢复工具,需要锁集群只读状态,无法满足一些场景的需求。本文通过物理文件备份方式,对表级备份恢复提供一种解决方案,一些限制和说明请参考总结部分。
1.1. 目标
通过物理文件的操作实现表数据的备份和还原。
- 备份数据完整性,表在还原后可正常使用
- 不影响非备份表的正常使用
1.2. 名词和约定
1.2.1. DbaUser
指数据库运行的【操作系统】用户,一般是gbase,后续全部用gbase做样例。
1.2.2. 安装目录
指数据库安装的具体目录。可以从环境变量里获得。比如
[root@rh6-1 ~]# cat /home/gbase/.gbase_profile |grep GCLUSTER_BASE=
export GCLUSTER_BASE=/opt/gcluster
[root@rh6-1 ~]# cat /home/gbase/.gbase_profile |grep GBASE_BASE=
export GBASE_BASE=/opt/gnode
表示安装目录是 /opt,后面例子我们也用这个目录作为安装目录演示。
1.2.3. 调度节点和计算节点
调度节点指 coordinator 服务节点,对应的目录为/opt/gcluster
计算/数据节点指 node服务节点,对应的目录为/opt/gnode
在GBase 8a里,调度节点只有表结构,不保存具体数据,所以备份时,只需要处理计算节点即可。
如下是gcadmin的输出,其中红色部分是调度节点,黄色部分是计算节点
后续例子,以这2节点集群为例。
1.2.4. 库文件
在计算节点里,库文件保存在库名相同的目录下
/opt/gnode/userdata/gbase/库名
后面例子中我们用testdb库做演示
/opt/gnode/userdata/gbase/testdb
1.2.5. 元数据目录和数据目录
在GBase 里,表数据分成2部分,其中
元数据保存路径为:/opt/gnode/userdata/gbase/testdb/metadata
数据保存路径为:/opt/gnode/userdata/gbase/testdb/sys_tablespace
1.2.6. 表和表结构
GBase 分成2种类型的表,复制表和分布表。表结构可以从如下SQL获得:
show create table 库名.表名
1.2.6.1. 复制表
在每个计算节点有一份完整的数据。比如表100万行,10个节点,那么每个节点都有100万上。如下是一个复制表的样例。
1.2.6.2. 分布表
数据在每个计算节点,按照分布规则(随机、Hash)分布式保存。同样100万行,10个节点,每个节点只保存部分数据,比如随机分布时,平均每个节点保存100/10=10万行。
如下是一个随机分布表的表结构例子:
如下是一个hash分布表的表结构例子:
因为复制表数据量少且每个节点都相同,容易修复,本备份还原主要针对分布表,后续例子以td表为例,数据3300万行,2个节点。
1.2.7. 表分片
针对分布表,计算节点上在表名字后面增加了分片号,并用下划线分割。如下是td分布表的表分片样例,包括2个分片,对应td_n1和td_n2。其中
metadata/td_n1.frm 文件为分片的表结构。一般随着建表语句自动生成,【无需】单独备份。
metadata/td_n1.GED 是元数据的目录,是我们的备份目标;
sys_tablesapce/td_n1是数据目录,是我们的备份目标;
对应的td_n2同样处理。
1.2.8. 分片的顺序和位置
通过如下命令,获得分布表在每个节点的顺序和位置。
gcadmin showdistribution
- 本例中有2个分片(Segment)1和2, 如下红色部分。
- 主分片(Primary segment)分别对应202和201上,如下红色部分;
- 备份分片(Duplicate Segment),分别对应201和202,如下蓝色部分;
提醒:本例只有2个节点,看上去是互备的,实际在节点多时,多数是循环备份的,比如3节点集群,1的备份在2,2的备份在3,3的备份在1。
该对应关系建议提前配置好,可以通过增加f参数输出XML格式方便程序解析。
gcadmin showdistribution f
1.2.9. 节点可连接状态
查看整个集群,哪些点可用,可以连接。
gcadmin
其中OPEN是正常, CLOSE表示服务停了,OFFLINE,表示节点无法连接(超时)。DataState部分,为0就是节点正常,1就是有表故障。
gcadmin输出的更多集群状态信息,可以参考 https://www.gbase8.cn/17
1.2.10. 节点nodeid
Nodeid是根据节点的标识,和IP对应,可以通过如下命令获得:
其中ID是节点的nodeid, ip是地址,后面的是主备情况和节点状态。
更多nodeid细节可以参考 https://www.gbase8.cn/1018
1.2.11. 表分片有效性
当主副本分片出现不一致时,可以通过如下方式,判断哪一个分片当前可用。
show datacopy map 库名.表名
其中dp_state为0代表正常。
更多细节可以参考 https://www.gbase8.cn/5788
如果是其它值,则表示该分片有故障,不能用于备份。
2. 表备份
2.1. 准备表结构
一定要准备表结构,避免整个表都出现故障,比如被误删,时恢复。请参考前面的表和表结构的部分,用show create table XXX获得。也可以业务提前准备好原始的建表语句。
2.2. 锁表
通过如下SQL语句,拿到表独占锁。如果有其它业务,包括DML和DDL操作,则会等待。
Lock table 表名 write;
拿到锁后,后来的DML/DDL操作同样会等待本连接释放锁。
gbase> lock table tdwrite;
Query OK, 0 rows affected (Elapsed: 00:00:00.00)
后续的操作,必须保证该连接不能断,否则锁会因为连接断开而被释放掉。
2.3. 备份表数据
按照每个节点的元数据和数据目录备份。其中对于有副本的,可以只备份一份,也就是td_n1只需要备份一份即可。
根据节点状态,表分片状态,备份每一个可用分片的数据。备份内容包括元数据目录和数据目录。
如下是通过scp从远端,统一备份到本地的操作,请根据实际情况备份文件。
scp -r gbase@10.0.2.201:/opt/gnode/userdata/gbase/testdb/sys_tablespace/td_n1 /opt/bak/testdb/td/
scp -r gbase@10.0.2.201:/opt/gnode/userdata/gbase/testdb/sys_tablespace/td_n2 /opt/bak/testdb/td/
scp -r gbase@10.0.2.201:/opt/gnode/userdata/gbase/testdb/metadata/td_n1.GED /opt/bak/testdb/td/
scp -r gbase@10.0.2.201:/opt/gnode/userdata/gbase/testdb/metadata/td_n2.GED /opt/bak/testdb/td/
备份结果如下,注意这里只有数据,没有表结构。
2.4. 释放锁
备份完毕后,通过unlock tables释放锁。
gbase> unlock tables;
Query OK, 0 rows affected (Elapsed: 00:00:00.00)
3. 表还原
3.1. 还原表结构
如果表已经丢失,或损坏严重,比如主副本都损坏且无法恢复,可以删除当前残留的表,然后通过备份的表结构,重建表。
另外,DROP表也会自动清除了表的故障event信息。
3.2. 锁表
请参考备份时的操作。
3.3. 还原数据
注意:
- 集群所有节点均【可以连接】时再做还原,除非【不可连接】节点处于节点故障需要替换状态。
- 备份时,我们只需要备份一个可用的分片即可,但还原时,如果副本可用,需要同时还原副本的分片。
- 还原时,请用操作系统gbase用户复制,可以确保数据文件复制后的属主正确,能被gbase用户读写访问。
根据当前集群的节点状态,按照分片主备顺序,将备份的分片,复制到对应的节点目录下。
比如td_n1分片,需要同时复制到当前可用的201和202节点。
scp -r /opt/bak/testdb/td/td_n1 gbase@10.0.2.201:/opt/gnode/userdata/gbase/testdb/sys_tablespace/
scp -r /opt/bak/testdb/td/td_n1 gbase@10.0.2.202:/opt/gnode/userdata/gbase/testdb/sys_tablespace/
注意主备分片的顺序,将元数据和数据分别复制到主备分片。
3.4. 修改数据文件属主
如果数据不是通过操作系统gbase用户复制,那么需要通过chown -R gbase:gbase 将每个节点复制过来的文件属主,改成正确的。否则数据可能无法读写访问,造成报错。比如
chown -R gbase:gbase /opt/gnode/userdata/gbase/testdb/sys_tablespace/td_n1
chown -R gbase:gbase /opt/gnode/userdata/gbase/testdb/metadata/td_n1.GED
。。。。。。
其它的同样处理
3.5. 刷新表
通过如下SQL,刷新表缓冲数据,之后就可以查询到表数据了。
refresh table 库名.表名;
本例中中间做了2次insert 操作测试表锁,所以比前面检查的多了2行。
3.6. 释放锁
请参考备份时的操作。
4. 总结
- 如果表结构有变动,增加减少了列,需要在备份数据时,对应备份表结构。
- 本方法无法实现增量备份,所以多次备份时请考虑是否要增加时间版本信息,以便恢复到指定日期的备份。
- 本方法只能实现单表级备份,无法保证多表之间的关系一致性。但如果一次性lock多个表,并立即同时备份可以达到该目的,但备份周期将延长,请根据实际情况取舍。
- 备份期间,表可以正常查询,但不能有DML/DDL操作,直到释放锁或连接断开。