ClickHouse数据备份
在ClickHouse中存在副本,主要作用是保证数据的高可用,副本不能防止数据误删这类操作,ClickHouse提供了多种数据备份的方法来防止数据误删。
一、导出文件备份
如果数据的体量较小,可以通过dump的形式将数据导出为本地文件,具体操作如下:
代码语言:javascript复制#在ClickHouse中创建表 test_backup
create table test_backup(
id UInt64,
name String,
age UInt8,
loc String
)engine=MergeTree()
order by id
partition by loc
#向表test_backup中插入如下数据
node1 :) insert into test_backup values (1,'zs',18,'beijing'),(2,'ls',19,'shanghai'),(3,'ww',20,'guangzhou'),(4,'ml',21,'beijing'),(5,'tq',22,'shanghai'),(6,'gb',23,'guangzhou');
执行导出数据命令:
代码语言:javascript复制#在node1节点创建导出数据目录“/software/data/”
[root@node1 ~]# mkdir -p /software/data/
#执行导出数据命令
[root@node1 ~]# ClickHouse-client --query="select * from test_backup" > /software/data/test_backup.tsv
注意:以上命令执行完成之后,会在“/software/data”目录下生成test_backup.tsv文件,数据默认按照tab隔开。
数据备份完成之后,需要还原到表时,可以执行如下命令:
代码语言:javascript复制#首先将表test_backup数据全部删除
node1 :) alter table test_backup delete where id >0;
#执行如下命令,将备份数据再次导入到表test_backup
[root@node1 data]# cat /software/data/test_backup.tsv |ClickHouse-client --query "Insert into test_backup format TSV"
注意:TSV格式必须大写。
#导入之后,查询表test_backup中的数据
node1 :) select * from test_backup;
二、通过快照表备份
快照表实质上就是普通的数据表,使用快照表备份时首先需要建立一张与原表结构相同的数据表,然后再使用“Insert into select ”句式将原有数据表写入到备份表。
假设test_backup表需要在1号这天做备份,步骤如下:
代码语言:javascript复制#创建备份表,备份表名称以当天日期结尾,只是创建了表
node1 :) create table test_backup_01 as test_backup;
#备份数据
node1 :) insert into test_backup_01 select * from test_backup;
#查询test_backup_01表中的数据
node1 :) select * from test_backup_01;
如果考虑到容灾问题,也可以将备份表放置在不同的ClickHouse节点上,此时备份数据的SQL如下:
代码语言:javascript复制insert into test_backup_01 select * from remote('node1:9000','default','test_backup','default','')
注意:remote中参数意义为remote(远程ClickHouse集群,连接ClickHouse库,备份的表,登录用户,用户密码)
测试如下:
代码语言:javascript复制#在node2节点登录ClickHouse,创建test_backup_01表
node2 :)create table test_backup_01(
id UInt64,
name String,
age UInt8,
loc String
)engine=MergeTree()
order by id
partition by loc ;
#然后在node2执行如下备份数据命令:
node2 :) insert into test_backup_01 select * from remote('node1:9000','default','test_backup','default','');
#在node2查询表test_backup_01表数据
node2 :) select * from test_backup_01;
三、按分区备份
基于数据分区的备份,ClickHouse目前提供了FREEZE与FETCH两种方式。
1、使用FREEZE备份
FREEZE的完整语法如下:
代码语言:javascript复制ALTER TABLE tb_name FREEZE PARTITION partition_expr
分区在备份之后,会统一保存到“/var/lib/ClickHouse/shadow/N”目录下,其中N是一个自增的整数,代表备份的次数(FREEZE执行的次数),具体次数由shadow子目录下的increment.txt文件记录。
使用FREEZE对分区进行备份测试:
在node1上对表test_backup分区“beijing”进行备份,具体操作如下:
代码语言:javascript复制#在node1中执行如下命令
node1 :) ALTER TABLE test_backup FREEZE PARTITION 'beijing';
以上命令执行完成之后,可以在“/var/lib/ClickHouse/shadow/1”下看到对应的数据。
在对应的数字目录中,目录结构为:/store/[database]/[table]/[partition_folder],如下:
对于备份的数据还原,需要借助ATTACH装载分区的方式实现,需要将shadow子目录下的分区文件复制到相应数据表的detached目录下,然后再使用ATTACH语句加载。
下面将备份的分区还原到表test_backup中,操作如下:
代码语言:javascript复制#将表test_backup表“beijing”分区删除
node1 :) alter table test_backup drop partition 'beijing';
#将备份的分区数据放入表test_backup数据目录下的detached目录下
[root@node1 ~]# cp -r /var/lib/ClickHouse/shadow/1/store/5eb/5eb930e9-8a99-4def-9eb9-30e98a997def/* /var/lib/ClickHouse/data/default/test_backup/detached/
#查看detached目录下的数据
[root@node1 detached]# ls /var/lib/ClickHouse/data/default/test_backup/detached
e8ccea18d4053730ef65315d1781f8c6_14_14_0
#修改分区数据对应的拥有者权限为ClickHouse
[root@node1 detached]# chown -R ClickHouse:ClickHouse e8ccea18d4053730ef65315d1781f8c6_14_14_0/
#给表test_backup表添加分区
node1 :) alter table test_backup attach partition 'beijing';
#查询表test_backup表中数据,数据还原成功
node1 :) select * from test_backup;
2、使用FETCH备份
FETCH 只支持ReplicatedMergeTree系列的表引擎,完整语法如下:
代码语言:javascript复制ALTER TABLE tb_name FETCH PARTITION partition_id FROM zk_path
其工作原理与ReplicatedMergeTree同步数据的原理类似,FETCH通过指定的zk_path找到ReplicatedMergeTree的所有副本实例,然后选择一个最合适的副本,下载相应的分区数据。
FETCH备份分区数据案例如下:
代码语言:javascript复制#在ClickHouse中创建ReplicatedMergeTree表 test_fetch
#在node1节点执行建表语句
Create table test_fetch(
id UInt32,
name String,
age UInt32,
gender String,
loc String
) engine = ReplicatedMergeTree('/ClickHouse/tables/01/test_fetch','node1')
partition by loc
order by id;
#在node2节点执行建表语句
Create table test_fetch(
id UInt32,
name String,
age UInt32,
gender String,
loc String
) engine = ReplicatedMergeTree('/ClickHouse/tables/01/test_fetch','node2')
partition by loc
order by id;
#在node1向表test_fetch中插入数据
insert into test_fetch values (1,'zs',18,'m','beijing'),(2,'ls',19,'f','shanghai'),(3,'ww',20,'m','beijing'),(4,'ml',21,'m','shanghai')
将表test_fetch “beijing”分区数据进行备份,在node1节点上执行如下命令:
代码语言:javascript复制ALTER TABLE test_fetch FETCH PARTITION 'beijing' FROM '/ClickHouse/tables/01/test_fetch'
执行以上命令之后,将对应分区的数据下载到当前节点本地“/var/lib/ClickHouse/data/{database}/{table}/detached”目录下:
与FREEZE一样,对分区数据进行还原时,需要借助ATTACH装载分区来实现,具体操作如下:
代码语言:javascript复制#在node1上删除表test_fetch “beijing”分区数据
node1 :) alter table test_fetch drop partition 'beijing';
#由于默认在detached中的数据权限为ClickHouse,不需要修改所有者,直接执行添加分区命令恢复备份数据即可
node1 :) alter table test_fetch attach partition 'beijing';
#查询表test_fetch中的数据
node1 :) select * from test_fetch;
FREEZE和FETCH虽然都能实现分区文件的备份,但不会备份数据表的元数据(也就是建表语句),为了做到万无一失的备份,还需要对元数据进行备份,元数据在“/var/lib/ClickHouse/metadata/{database}”目录下,找到对应表的sql文件单独保存即可。