常见备份方式概览
备份方式 | 特点 |
---|---|
物理文件备份 | 对物理文件进行拷贝,备份期间禁止数据写入 |
dump数据导入导出 | 备份方式灵活,但备份速度慢 |
快照表备份 | 制作_bak表进行备份 |
FREEZE备份 | 表(分区表、非分区表)分区备份,可通过attach进行装载恢复 |
FETCH备份 | ReplicaMergeTree引擎的分区表分区备份,可通过attach进行装载恢复 |
元数据备份 | 建表、建库语句备份 |
常见恢复方式概览
恢复方式 | 特点 |
---|---|
attach | 通过对表分区的备份文件进行装载恢复,需要将备份文件放在对应的detached目录下 |
一、冷备
通过对物理文件的拷贝也可达到备份的效果,但是需要注意的是通过拷贝物理文件进行备份期间,要避免数据写入。
物理文件的备份主要分为两部分:
- 表数据文件备份,${datadir}/data下可对某个数据库、某张表、某个分区文件进行备份
- 元数据备份,${datadir}/metadata下可对某个数据库、某张表的建表语句进行备份
二、热备
2.1 数据导入导出
通过查询语句将指定数据导出到tsv文件进行备份,备份数据比较灵活,并且可通过客户端工具进行数据导入恢复。
1、基本语法
-- 导出
clickhouse-client -h ${host} -p ${port} --user=${username} --password=${password} --query="select * from ${table_name}" > ${table_name}.tsv
-- 导入
cat ${table_name}.tsv | clickhouse-client -h ${host} -p ${port} --user=${username} --password=${password} --query "insert into ${table_name} format TSV";
-- 流式导入导出
clickhouse-client -h ${host} -p ${port} --user=${username} --password=${password} --query="select * from <db>.<table_name> FORMAT CSV" |
clickhouse-client -h ${host} -p ${port} --user=${username} --password=${password} --query="INSERT INTO <db>.<table_name> FORMAT CSV"
2、示例
1)导出数据到本地文件
# clickhouse-client -h 172.16.104.11 --query="select * from db1.t7_all" > t7_all.tsv
# cat t7_all.tsv
1 aa
3 cc
4 dd
5 ee
2 bb
2)导入备份文件进行恢复
-- 创建表
mdw :) create table t7_bak_local on cluster shard2_repl0 (`id` Int32,`name` String) engine=ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/t7_bak_local','{replica}') order by id;
mdw :) create table t7_bak_all on cluster shard2_repl0 (`id` Int32,`name` String) engine=Distributed(shard2_repl0,db1,t7_bak_local,rand());
-- 导入数据
# cat t7_all.csv | clickhouse-client -h 172.16.104.11 --query "insert into t7_bak_all format TSV";
-- 验证数据
mdw :) select * from t7_bak_all order by id;
SELECT *
FROM t7_bak_all
ORDER BY id ASC
┌─id─┬─name─┐
│ 1 │ aa │
│ 2 │ bb │
│ 3 │ cc │
│ 4 │ dd │
│ 5 │ ee │
└────┴──────┘
5 rows in set. Elapsed: 0.019 sec.
2.2 快照表
快照表其实就是创建一个与需要进行备份的表表结构相同的一个bak表,并将数据写入bak表进行备份。
1、基本语法
-- 创建备份表,对于分布式表或者复制表可通过手动指定engine进行区分
create table ${table_name}_bak as ${table_name} ;
create table ${table_name}_bak as ${table_name} engine=xxx order by xx;
-- 备份数据
insert into ${table_name}_bak select * from ${table_name} ;
2、示例
1)创建快照表
-- 创建快照表
mdw :) create table db1.t2 on cluster shard2_repl0 as db1.t7_all ENGINE = Distributed('shard2_repl0', 'db1', 't2_local', rand());
mdw :) create table db1.t2_local on cluster shard2_repl0 as db1.t7_local ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/t2_local','{replica}') order by id;
2)备份数据
-- 导入数据
mdw :) insert into t2 select * from t7_all ;
mdw :) select * from t2 order by id;
SELECT *
FROM t2
ORDER BY id ASC
┌─id─┬─name─┐
│ 1 │ aa │
│ 2 │ bb │
│ 3 │ cc │
│ 4 │ dd │
│ 5 │ ee │
└────┴──────┘
5 rows in set. Elapsed: 0.014 sec.
2.3 FREEZE备份
Freeze是基于分区来进行备份的,通过freeze对指定分区进行备份后,CK会将改分区的数据存储在${datadir}/shadow目录下,shadow目录下的N是一个自增长的整数,表示freeze执行的次数。
freeze的备份本质上是通过对原始目录文件进行硬链接实现的,所以不会导致额外的空间存储上涨。
1、基本语法
对于非分区表,ck其实将其认为是仅有一个all的分区表来看,使用freeze时不添加parttion条件即可。
alter table ${table_name} freeze [partition ${partition_expr}];
2、示例
1)分区表
-- 备份数据
sdw1 :) alter table t7 freeze partition 202101;
sdw1 :) alter table t7 freeze partition 202102;
-- 查看shadow目录
[root@sdw1 shadow]# pwd
/data/clickhouse-server/data/shadow
[root@sdw1 shadow]# ll
总用量 4
drwxr-x--- 3 clickhouse clickhouse 18 2月 18 22:16 1
drwxr-x--- 3 clickhouse clickhouse 18 2月 18 22:24 2
-rw-r----- 1 clickhouse clickhouse 2 2月 18 22:24 increment.txt
-- 查看备份数据
[root@sdw1 t7]# pwd
/data/clickhouse-server/data/shadow/1/data/db1/t7
[root@sdw1 t7]# ll
总用量 0
drwxr-x--- 2 clickhouse clickhouse 279 2月 18 22:16 202101_5_5_0
[root@sdw1 t7]# pwd
/data/clickhouse-server/data/shadow/2/data/db1/t7
[root@sdw1 t7]# ll
总用量 0
drwxr-x--- 2 clickhouse clickhouse 279 2月 18 22:24 202102_4_4_0 # 对于分区表,每个分区为一个分区目录
2)非分区表
-- 备份数据
sdw3 :) alter table tt1 freeze;
-- 查看备份数据
[root@sdw3 tt1]# pwd
/data/clickhouse-server/data/shadow/1/data/db1/tt1
[root@sdw3 tt1]# ll
总用量 0
drwxr-x--- 2 clickhouse clickhouse 181 2月 24 16:55 all_1_1_0 # 对于非分区表,默认为all一个分区
2.4 FETCH备份
fetch仅仅针对 ReplicaMergeTree 引擎的表。其工作原理与 ReplicatedMergeTree同步数据的原理类似, FETCH 通过指定的 zk_path 找到对应所有的数据文件并进行下载,将备份文件存储在 d a t a d i r / d a t a / {datadir}/data/ datadir/data/{db}/${table_name}/detached 目录下。
1、基本语法
alter table ${table_name} fetch partition ${partition_expr} from '${zk_path}'
2、示例
-- 数据准备
sdw1 :) create table t8 on cluster shard1_repl1(`id` Int32,`name` String,`create_date` Date) engine = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/t8','{replica}') PARTITION BY toYYYYMM(create_date) order by id
sdw1 :) insert into t8 values (6,'dsk','2020-07-20'),(4,'ww','2020-01-02'),(19,'bw','2021-02-18'),(17,'bb','2021-01-02'),(12,'aw','2021-01-02'),(21,'cc','2020-01-08'),(32,'ww','2020-02-02');
-- 备份数据
sdw1 :) alter table t8 fetch partition 202101 from '/clickhouse/tables/01-01/t8'; # from后的路径为zk_path的路径,可查看表结构
-- 备份数据
[root@sdw1 202101_0_0_0]# pwd
/data/clickhouse-server/data/data/db1/t8/detached/202101_0_0_0
[root@sdw1 202101_0_0_0]# ls
checksums.txt columns.txt count.txt create_date.bin create_date.mrk2 default_compression_codec.txt id.bin id.mrk2 minmax_create_date.idx name.bin name.mrk2 partition.dat primary.idx
三、数据恢复
物理文件的备份、freeze备份、fetch备份均可以通过attach进行装载,完成数据恢复,需要注意的是:
- 物理文件备份、freeze备份、fetch备份时,需要关注对元数据进行备份,避免元数据丢失,数据文件无法进行恢复
- 使用fetch备份表分区文件后,备份文件存储在 d a t a d i r / d a t a / {datadir}/data/ datadir/data/{db}/${table_name}/detached 目录下,可直接通过attach命令进行装载
- 使用freeze备份表分区文件后,备份文件存储在${datadir}/shadow目录下,若需要进行数据恢复,需要将该目录下的备份文件拷贝到对应的detached目录下,然后进行装载恢复
- 使用物理文件备份需要将需要恢复的文件拷贝到对应的detached目录下,然后进行装载恢复
1、基本语法
对于备份分区的还原操作,则需要借助 ATTACH 装载分区的方式来实现 。
1)对于分区表
如果要还原分区表的分区数据,首先需要主动将shadow子目录下的分区文件复制到相应数据表的 detached 目录下,然后再使用 ATTACH 语句装载 。
-- 对于分区表,需要提前创建表结构
ALTER TABLE ${tablename} ATTACH PARTITION ${partition_expr};
2)对于非分区表
如果要还原分区表的分区数据,需要主动将all相关的分区目录备份放在对应的表数据目录下,使用 DETACH 语句卸载、ATTACH 语句装载 。
-- 对于非分区表,需要提前创建表结构
ATTACH TABLE ${tablename}
DETACH TABLE ${tablename}
2、示例
alter table t8 attach partition 202102;