在使用数据库的过程中,总有一些原因会造成数据的丢失,如操作人员误删、黑客恶意攻击、服务器硬件故障等,备份恢复技术是保证数据丢失后仍然能够恢复使用的最后一道防线。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中的备份与恢复有哪些能力及备份恢复的基本使用方法,对于细节部分没有作过多说明,读者可自行参考官网相关内容。