作者: 数据源的 TiDB 学习之路原文来源:https://tidb.net/blog/71f2bc64
在使用数据库的过程中,总有一些原因会造成数据的丢失,如操作人员误删、黑客恶意攻击、服务器硬件故障等,备份恢复技术是保证数据丢失后仍然能够恢复使用的最后一道防线。TiDB 作为一款原生分布式数据库,完整的支持数据库各项备份及恢复能力,然而,由于架构本身的特点,其备份恢复的执行原理与普通数据库有所不同。本文整体描述 TiDB 的备份与恢复能力。
关于 TiDB 的备份能力
TiDB 的备份分为物理备份和逻辑备份两种。物理备份是直接备份物理文件 (.SST) 的方式,具体又分为全量备份和增量备份;逻辑备份是将数据导出到二进制或文本文件中。物理备份通常是针对数据量较大的集群级别或数据库级别备份,能够保证备份数据的一致性;逻辑备份则主要是针对数据量较小或表个数较少的全量备份,在业务运行的情况下不保证备份数据的一致性。
物理备份
物理备份分为全量备份和增量备份。全量备份又称为“快照备份”,即通过快照保证备份出的数据一致;增量备份在当前的 TiDB 版本中又称为“日志备份”,即每次备份最近一个时间范围的 kv 变更日志。
快照备份
快照备份的完整流程为:
BR 接收备份命令 br backup full。获得备份快照点和备份存储地址。
BR 调度备份数据。具体步骤包括:1 暂停 GC,防止被备份数据被 GC 回收;2 访问 PD 获取被备份数据的 Region 分布信息及 TiKV 节点信息;3 创建备份请求发送给 TiKV 节点,包含 backup ts、备份的 region、备份存储地址。
TiKV 接受备份请求并初始化 backup worker。
TiKV 备份数据。具体步骤包括:1 读取数据,由 backup worker 从 Region Leader 读 backup ts 对应数据;2 保存到 SST 文件,存储在内存中;3 上传 SST 文件到备份存储。
BR 从各个 TiKV 获取备份结果。如果 Region 变动会重试,如果不可重试则备份失败。
BR 备份元信息。备份 table schema,计算 table data checksum,生成 backup metadata,并上传到备份存储。
要执行一个快照备份,推荐方法是使用 TiDB 提供的 br 命令行工具,可以使用 tiup install br 进行安装。安装 br 后,便可以使用相关命令进行快照备份,目前快照备份支持集群级、数据库级以及表级别的备份,以下为使用 br 进行集群快照备份的示例。关于库级备份及表级备份的语法可参考 TiDB 快照备份与恢复命令行手册 | PingCAP 文档中心。
[tidb@tidb53 ~]$ tiup br backup full --pd "172.20.12.52:2679" --storage "local:///data1/backups" --ratelimit 128 --log-file backupfull.log
tiup is checking updates for component br ...
Starting component `br`: /home/tidb/.tiup/components/br/v7.6.0/br backup full --pd 172.20.12.52:2679 --storage local:///data1/backups --ratelimit 128 --log-file backupfull.log
Detail BR log in backupfull.log
[2024/03/05 10:19:27.437 +08:00] [WARN] [backup.go:311] ["setting `--ratelimit` and `--concurrency` at the same time, ignoring `--concurrency`: `--ratelimit` forces sequential (i.e. concurrency = 1) backup"] [ratelimit=134.2MB/s] [concurrency-specified=4]
Full Backup <----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
Checksum <-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
[2024/03/05 10:20:29.456 +08:00] [INFO] [collector.go:77] ["Full Backup success summary"] [total-ranges=207] [ranges-succeed=207] [ranges-failed=0] [backup-checksum=1.422780807s] [backup-fast-checksum=17.004817ms] [backup-total-ranges=161] [total-take=1m2.023929601s] [BackupTS=448162737288380420] [total-kv=25879266] [total-kv-size=3.587GB] [average-speed=57.82MB/s] [backup-data-size(after-compressed)=1.868GB] [Size=1867508767]
[tidb@tidb53 ~]$ ll /data1/backups/
总用量 468
drwxr-xr-x. 2 nfsnobody nfsnobody 20480 3月 5 10:20 1
drwxr-xr-x. 2 tidb tidb 12288 3月 5 10:20 4
drwxr-xr-x. 2 nfsnobody nfsnobody 12288 3月 5 10:20 5
-rw-r--r--. 1 nfsnobody nfsnobody 78 3月 5 10:19 backup.lock
-rw-r--r--. 1 nfsnobody nfsnobody 395 3月 5 10:20 backupmeta
-rw-r--r--. 1 nfsnobody nfsnobody 50848 3月 5 10:20 backupmeta.datafile.000000001
-rw-r--r--. 1 nfsnobody nfsnobody 365393 3月 5 10:20 backupmeta.schema.000000002
drwxrwxrwx. 3 nfsnobody nfsnobody 4096 3月 5 10:19 checkpoints
复制代码
上述 –ratelimit 表示每个 TiKV 执行备份任务的速度上限为 128MB/s,–log-file 表示将备份日志写入的目标文件,–pd 指定 PD 节点。Br 命令中还支持 –backupts 参数,表示备份快照对应的物理时间点,未指定此参数表示使用当前时间点作为快照时间点。
如果我们想从一个已完成的备份集中判断这个快照备份是基于什么时间点进行的,br 也提供相应的命令 br validate decode,此命令的输出是一串 TSO,我们可以使用 tidb_parse_tso 将其解析为物理时间,如下所示。
[tidb@tidb53 ~]$ tiup br validate decode --field="end-version" --storage "local:///data1/backups" | tail -n1
tiup is checking updates for component br ...
Starting component `br`: /home/tidb/.tiup/components/br/v7.6.0/br validate decode --field=end-version --storage local:///data1/backups
Detail BR log in /tmp/br.log.2024-03-05T10.24.25+0800
448162737288380420
mysql> select tidb_parse_tso(448162737288380420);
+------------------------------------+
| tidb_parse_tso(448162737288380420) |
+------------------------------------+
| 2024-03-05 10:19:28.489000 |
+------------------------------------+
1 row in set (0.01 sec)
复制代码
日志备份
日志备份的完整流程为:
BR 接收备份命令 br log start。解析获取日志备份任务的 checkpoint ts、备份存储地址,在 PD 注册日志备份任务。
TiKV 监控日志备份任务的创建与更新。每个 TiKV 节点的 log backup observer 监听 PD 中日志备份任务的创建与更新,并备份该节点上在备份范围内的数据。
TiKV log backup observer 持续备份 KV 变更日志。具体步骤包括:1 读取 KV 数据变更保存到自定义格式备份文件;2 定期从 PD 查询 global checkpoint ts;3 定期生成 local metadata;定期将日志备份数据和 local metadata 上传到备份存储;4 请求 PD 阻止未备份数据被 GC 回收。
TiDB Coordinator 监控日志备份进度。轮询所有 TiKV 节点获取各个 Region 备份进度,根据 Region checkpoint ts 计算整个日志备份任务的进度并上传给 PD。
PD 持久化日志备份任务状态。通过 br log status 查询。
快照备份的命令以 br backup …开头,而日志备份的命令以 br log…开头。启动一个日志备份的命令就是 br log start,日志备份任务启动后使用 br log status 来查询日志备份的任务状态。
[tidb@tidb53 ~]$ tiup br log start --task-name=pitr --pd "172.20.12.52:2679" --storage "local:///data1/backups/pitr"
tiup is checking updates for component br ...
Starting component `br`: /home/tidb/.tiup/components/br/v7.6.0/br log start --task-name=pitr --pd 172.20.12.52:2679 --storage local:///data1/backups/pitr
Detail BR log in /tmp/br.log.2024-03-05T10.50.52+0800
[2024/03/05 10:50:53.013 +08:00] [INFO] [collector.go:77] ["log start"] [streamTaskInfo="{taskName=pitr,startTs=448163231285641223,endTS=999999999999999999,tableFilter=*.*}"] [pausing=false] [rangeCount=2]
[2024/03/05 10:50:55.237 +08:00] [INFO] [collector.go:77] ["log start success summary"] [total-ranges=0] [ranges-succeed=0] [ranges-failed=0] [backup-checksum=20.167609ms] [total-take=2.355842192s]
[tidb@tidb53 ~]$ ll /data1/backups/pitr/
总用量 368
-rw-r--r--. 1 nfsnobody nfsnobody 78 3月 5 10:50 backup.lock
-rw-r--r--. 1 nfsnobody nfsnobody 364601 3月 5 10:50 backupmeta
drwxr-xr-x. 5 nfsnobody nfsnobody 4096 3月 5 10:53 v1
复制代码
以上命令中,–task-name 参数指定日志备份任务的名称,–pd 指定 pd 节点,–storage 指定日志备份地址。Br log 还支持 –start-ts 参数,指定开始备份日志的起始时间,未指定则代表使用当前时间作为 start-ts。
[tidb@tidb53 ~]$ tiup br log status --task-name=pitr --pd "172.20.12.52:2679"
tiup is checking updates for component br ...
Starting component `br`: /home/tidb/.tiup/components/br/v7.6.0/br log status --task-name=pitr --pd 172.20.12.52:2679
Detail BR log in /tmp/br.log.2024-03-05T10.56.28+0800
● Total 1 Tasks.
> #1 <
name: pitr
status: ● NORMAL
start: 2024-03-05 10:50:52.939 +0800
end: 2090-11-18 22:07:45.624 +0800
storage: local:///data1/backups/pitr
speed(est.): 0.00 ops/s
checkpoint[global]: 2024-03-05 10:55:42.69 +0800; gap=47s
[tidb@tidb53 ~]$ tiup br log status --task-name=pitr --pd "172.20.12.52:2679"
tiup is checking updates for component br ...
Starting component `br`: /home/tidb/.tiup/components/br/v7.6.0/br log status --task-name=pitr --pd 172.20.12.52:2679
Detail BR log in /tmp/br.log.2024-03-05T10.58.57+0800
● Total 1 Tasks.
> #1 <
name: pitr
status: ● NORMAL
start: 2024-03-05 10:50:52.939 +0800
end: 2090-11-18 22:07:45.624 +0800
storage: local:///data1/backups/pitr
speed(est.): 0.00 ops/s
checkpoint[global]: 2024-03-05 10:58:07.74 +0800; gap=51s
复制代码
上面输出显示日志备份的状态为正常,通过两次输出对比,可以发现日志备份任务在后台确实是在定期执行备份任务,其中 checkpoint[global]意味着集群中早于该 checkpoint 时间点的数据都已经保存在备份存储,它是备份数据可恢复的最近时间点。
逻辑备份
逻辑备份简单理解就是使用 TiDB 的 SQL 语句或导出工具将数据导出来。除了常用的导出语句,TiDB 提供一款叫 Dumpling 的工具,可以把存储在 TiDB 或 MySQL 中的数据导出为 SQL 或 CSV 格式。Dumpling 的详细文档请参考 使用 Dumpling 导出数据 | PingCAP 文档中心, 本文不作赘述。一个典型的 Dumpling 示例如下,它表示导出目标数据库中所有非系统表数据,导出格式为 SQL 文件、导出并发线程数为 8、输出目录为 /tmp/test、按 200K 记录开启表内并发加速导出、导出单个文件大小为 256MB。
dumpling -u root -P 4000 -h 127.0.0.1 --filetype sql -t 8 -o /tmp/test -r 200000 -F256MiB
复制代码
关于 TiDB 的恢复能力
TiDB 的恢复可以分为基于物理备份的恢复和基于逻辑备份的恢复。基于物理备份的恢复是指通过 br restore 命令行方式进行恢复,通常是针对大数据量的全量数据还原;基于逻辑备份的恢复是指数据导入,比如将上述 Dumpling 导出的文件导入到集群中,通常是针对小数据量或表数量较少的数据导入。
物理恢复
物理恢复分为两种:一种是直接恢复到某个快照备份,这种方式只需要指定快照备份的备份存储路径;另一种是 PITR(Point-in-time Recovery),即时间点恢复,它不仅需要指定备份存储路径 (包括快照备份数据和日志备份数据),还需要指定要恢复的时间点。
快照备份恢复
快照恢复的完整流程为(上述快照备份图例已包含):
BR 接收恢复命令 br restore。获得快照备份存储地址、要恢复的对象,同时检查要恢复的对象是否存在及是否符合要求。
BR 调度恢复数据。具体步骤包括:请求 PD 关闭自动 Region 调度、读取并恢复备份数据的 schema、基于备份数据信息请求 PD 分配 Region 并将 Region 分布到 TiKV、根据 PD 分配的 Region 结果发送恢复请求到 TiKV。
TikV 接受恢复请求并初始化 restore worker。
TiKV 恢复数据。具体步骤包括:从备份存储下载数据到本地、restore worker 对备份数据 kv 进行重写 (替换 table id 及 index id)、将处理好的 SST 文件注入到 RocksDB、返回恢复结果给 BR。
BR 从各 TiKV 获取恢复结果。
快照备份恢复可以基于集群级别、库级别以及表级别。建议恢复到一个空集群,如果待恢复对象在集群中已存在会导致恢复出错 (系统表除外)。以下为一个集群恢复的示例,
[tidb@tidb53 ~]$ tiup br restore full --pd "172.20.12.52:2679" --storage "local:///data1/backups"
tiup is checking updates for component br ...
Starting component `br`: /home/tidb/.tiup/components/br/v7.6.0/br restore full --pd 172.20.12.52:2679 --storage local:///data1/backups
Detail BR log in /tmp/br.log.2024-03-05T13.08.08+0800
Full Restore <---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
[2024/03/05 13:08:27.918 +08:00] [INFO] [collector.go:77] ["Full Restore success summary"] [total-ranges=197] [ranges-succeed=197] [ranges-failed=0] [split-region=786.659µs] [restore-ranges=160] [total-take=19.347776543s] [RestoreTS=448165390238351361] [total-kv=25811349] [total-kv-size=3.561GB] [average-speed=184MB/s] [restore-data-size(after-compressed)=1.847GB] [Size=1846609490] [BackupTS=448162737288380420]
复制代码
如果要恢复单个库,只需要在恢复命令中增加 –db 参数;如果要恢复单个表,需要在恢复命令中增加 –db 和 –table 参数。
PITR
PITR 的恢复命令为 br restore point…。对于初始化恢复集群,必须指定快照备份,使用 –full-backup-storage 指定快照备份的存储地址。使用 –restored-ts 指定恢复到的时间点,未指定此参数代表恢复到最后可恢复的时间点。另外如果只恢复日志备份数据的话,需要使用 –start-ts 指定日志备份恢复的起始时间点。以下是一个包含快照恢复的时间点恢复示例:
[tidb@tidb53 ~]$ tiup br restore point --pd "172.20.12.52:2679" --full-backup-storage "local:///data1/backups/fullbk" --storage "local:///data1/backups/pitr" --restored-ts "2024-03-05 13:38:28+0800"
tiup is checking updates for component br ...
Starting component `br`: /home/tidb/.tiup/components/br/v7.6.0/br restore point --pd 172.20.12.52:2679 --full-backup-storage local:///data1/backups/fullbk --storage local:///data1/backups/pitr --restored-ts 2024-03-05 13:38:28+0800
Detail BR log in /tmp/br.log.2024-03-05T13.45.02+0800
Full Restore <---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
[2024/03/05 13:45:24.620 +08:00] [INFO] [collector.go:77] ["Full Restore success summary"] [total-ranges=111] [ranges-succeed=111] [ranges-failed=0] [split-region=644.837µs] [restore-ranges=75] [total-take=21.653726346s] [BackupTS=448165866711285765] [RestoreTS=448165971332694017] [total-kv=25811349] [total-kv-size=3.561GB] [average-speed=164.4MB/s] [restore-data-size(after-compressed)=1.846GB] [Size=1846489912]
Restore Meta Files <......................................................................................................................................................................................> 100%
Restore KV Files <........................................................................................................................................................................................> 100%
[2024/03/05 13:45:26.944 +08:00] [INFO] [collector.go:77] ["restore log success summary"] [total-take=2.323796546s] [restore-from=448165866711285765] [restore-to=448165867159552000] [restore-from="2024-03-05 13:38:26.29 +0800"] [restore-to="2024-03-05 13:38:28 +0800"] [total-kv-count=0] [skipped-kv-count-by-checkpoint=0] [total-size=0B] [skipped-size-by-checkpoint=0B] [average-speed=0B/s]
复制代码
逻辑恢复
逻辑恢复也可以理解为数据导入,除了使用通用的 SQL 导入以外,TiDB 支持 Lightning 工具导入数据,Lightning 是用于从静态文件导入数据到 TiDB 集群的工具,常用于 TiDB 集群的初始经数据导入,具体可参考官网 TiDB Lightning 简介 | PingCAP 文档中心。
本文详细总结了 TiDB 中的备份与恢复有哪些能力及备份恢复的基本使用方法,对于细节部分没有作过多说明,读者可自行参考官网相关内容。
评论