Clickhouse数据备份与恢复

Posted by Lance Lee on Monday, August 10, 2020

TOC

一 数据备份与恢复

Clickhouse的ReplicatedMergeTree支持数据副本,具有冗灾的特性,但是数据备份还是需要,因为数据副本不能解决误删除的问题。Clickhouse本身提供了多种备份数据的方法,根据数据规模的不同,可以选择不同的方式。

1.1 导出文件备份

若数据量较小,可以通过dump的形式将数据导出为本地文件。

clickhouse-client -d database --query="SELECT * FROM [db.]tablename format CSV" > export_tablename.csv

将备份导入,执行以下语句。

cat export_tablename.csv | clickhouse-client --query="INSERT INTO [db.]tablename FORMAT CSV";

1.2 通过快照表备份

快照表本质上就是普通的数据表,通常按照业务规定的备份频率创建,例如按天或者按月创建。所以需要先建立一张与源表结构相同的数据表,然后再使用INSERT INTO SELECT语句,点对点的将数据从源表写入备份表

# 适用于MergeTree,ReplicatedMergeTree表引擎不能使用AS
CREATE TABLE test_backup_0817 AS test;

INSERT INTO TABLE test_backup_0817 SELECT * FROM test;

考虑到容灾问题,可以将备份表放置到其他的Clickhouse节点上,此时需要将上面的查询语句改为远程查询的形式。

INSERT INTO TABLE test_backup_0817 SELECT * FROM remote('172.31.5.21:9000', 'default', 'test', 'default');

1.3 按分区备份

分布式表不支持分区操作,分区备份只能对本地表进行备份。

1 使用FREEZE备份

FREEZE备份的语法如下:

ALTER TABLE [db.]tablename FREEZE PARTITION partition_expr;

分区被备份之后,会统一保存到Clickhouse根路径/shadow/N子目录下。其中,N是一个自增长的整数,它的含义是备份的次数(FREEZE执行过多少次),具体次数由shadow子目录下的increment.txt文件记录。而分区备份实质上是对原始目录文件进行硬链接操作,所以并不会导致额外的存储空间。整个备份的目录会一直向上追溯至data根路径的整个链路:

/data/[database]/[table]/[partition_folder]

例如,对datasets数据库中hits_v2表的201403分区进行备份。可以在/var/lib/clickhouse/shadow/1/data目录下查看备份。

ALTER TABLE datasets.hits_v2 FREEZE PARTITION 201403;

对于备份分区的还原操作,需要借助分区操作ATTACH装载分区实现。如果要还原数据,首先需要主动将shadow子目录下的分区文件复制到相应数据表的detached目录下,然后再使用ATTACH语句装载。

2 使用FETCH备份

FETCH只支持ReplicatedMergeTree系列的表引擎,语法如下:

ALTER TABLE tablename FETCH PARTITION partition_id FROM zk_path;

其工作原理与ReplicatedMergeTree同步数据的原理类似,FETCH通过指定的zk_path找到ReplicatedMergeTree的所有副本实例,然后从中选择一个最合适的副本,并下载相应的分区数据到对应数据表的detached目录下。

例如执行下面的语句,可以将test_fetch的2019分区下载到本地,并保持到对应数据表的detached目录下:

ALTER TABLE test_fetch FETCH PARTITION 2019 FROM '/clickhouse/tables/datasets/01-01/hits_v2';

与FREEZE一样,对于备份分区的还原操作,同样是通过ATTACH装载分区实现。

3 ATTACH装载分区

ATTACH操作可以装载数据表的detached目录下的分区数据。语法如下:

ALTER TABLE tablename ATTACH PARTITION partition_expr;

以FETCH备份中test_fetch为例,装载2019分区

ALTER TABLE test_fetch ATTACH PARTITION 2019;

1.4 物理备份

其实,Clickhouse可以直接对数据目录进行物理拷贝。需要注意的是,拷贝时不能写入,否则损坏数据文件,因此可以用于历史数据的拷贝。

若需要对某个数据库备份,直接拷贝节点的/data/database目录和/metadata/database目录;若需要对整个表备份,直接拷贝整个表的目录即可;如果是对某个分区进行拷贝,需要拷贝该分区对应的所有数据片段。

备份恢复可以通过ATTACH装载分区实现,也可以利用启动时自动装载实现。若通过ATTACH装载,需要将所有分区目录放到相应数据表的detached目录下,然后使用ATTCH命令装载。若通过启动时自动装载实现,需要先创建表,然后关闭服务器,并将整个数据目录放到相应数据表的根目录下,然后启动服务器即可。

下面以备份节点为例。

mkdir -p /tmp/data/datasets && cp -r /var/lib/clickhouse/data/datasets/ /tmp/data
mkdir -p /tmp/metadata/datasets && cp -r /var/lib/clickhouse/metadata/datasets/ /tmp/metadata

clickhouse-client -m --query "DROP TABLE datasets.hits_v1"

cp -r /tmp/data/datasets/hits_v1 /var/lib/clickhouse/data/datasets/ && cp /tmp/metadata/datasets/hits_v1.sql /var/lib/clickhouse/metadata/datasets/

# 需要修改组,否则会报权限问题
chown clickhouse:489 -R /var/lib/clickhouse/data/datasets/hits_v1 && chown clickhouse:489 /var/lib/clickhouse/metadata/datasets/hits_v1.sql

service clickhouse-server restart

clickhouse-client --query "SELECT COUNT(*) FROM datasets.hits_v1"

可以看到数据已经完成恢复。

二 元数据备份

表的数据分为数据和元数据两部分,如果想做到万无一失,还需要对数据表的元数据进行备份。

2.1 拷贝建表语句

在clickhouse根路径/metadata/下存储了建表语句,可以直接拷贝进行备份。

里面的建表语句其实是装载表的语句,其他场景可以修改ATTACH为CREATE。

2.2 命令备份

利用SHOW CREATE TABLE命令导出建表语句,语法如下:

clickhouse-client --query="SHOW CREATE TABLE [db.]tablename" > tablename.sql

例如,导出173节点上RISK库中NETPAYMENTTX_TEMP_BAK_BEFORECLEAN表的建表语句

clickhouse-client -h 172.31.1.173 --port 9000 --query="SHOW CREATE TABLE RISK.NETPAYMENTTX_TEMP_BAK_BEFORECLEAN" > NETPAYMENTTX_TEMP_BAK_BEFORECLEAN.sql

「如果这篇文章对你有用,请支持一下哦」

Attack On Programmer

如果这篇文章对你有用,请支持一下哦

使用微信扫描二维码完成支付