From ebb3aaffd4962da013fe64c61c2f9bc5d8f41b16 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Thu, 7 Nov 2019 13:18:36 +0800 Subject: [PATCH 01/20] Add br doc Signed-off-by: Neil Shen --- dev/reference/tools/br.md | 264 ++++++++++++++++++++++++++++++++++++++ media/br-arch.png | Bin 0 -> 75987 bytes 2 files changed, 264 insertions(+) create mode 100644 dev/reference/tools/br.md create mode 100644 media/br-arch.png diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md new file mode 100644 index 000000000000..437d19a1ce69 --- /dev/null +++ b/dev/reference/tools/br.md @@ -0,0 +1,264 @@ +--- +title: BR 使用说明 +category: reference +--- + +# BR 使用说明 + +BR 是分布式备份恢复的命令行工具,用于管理分布式备份恢复。 + +如果通过 Ansible 部署集群,则对应的 `tidb-ansible/resources/bin` 目录下会存在 `br` +二进制文件。如果使用二进制文件部署集群,bin 目录下会包含 `br` 文件及 `tidb-server`、 +`pd-server`、以及 `tikv-server` 等其他文件。 + +## 原理介绍 + +BR 是管理分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后 +执行真正的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的 +备份文件将会保存在该路径下,恢复时也会从该路径读取的相应的备份文件。 + +![br-arch](/media/br-arch.png) + +## 使用介绍 + +`br` 的使用由命令(包括子命令)、选项和参数组成。命令即不带 `-` 或者 `--` 的字符, +选项即带有 `-` 或者 `--` 的字符,参数即命令或选项字符后紧跟的传递给命令和选项的字符。 + +如:`br --pd "$IP:2379" backup full -s "local:///tmp/backup"` +如:`br schema in mysql -n db` + +* backup: 命令 +* full: backup 的子命令 +* -s/--storage: 备份保存的路径 +* `"local:///tmp/backup"`: -s 的参数,保存的路径为本地磁盘的 `/tmp/backup`。 +* --pd: PD 服务地址 +* `"$IP:2379"`: --pd 的参数 + +### 获取帮助 + +`br -h/--help` 用于获取帮助信息。br 由多层命令组成,br 及其所有子命令都可以通过 +`-h/--help` 来获取使用帮助。 + +### 连接 + +`br` 与连接相关的参数有 2 个,分别为: + +- `--pd` PD 服务地址 +- `--connect` TiDB 服务地址 + +其中 `--connect` 用于 `restore` 子命令,例如:`br restore table`。 +使用 br 备份恢复功能时必须指定这两个参数,否则会报错退出。 + +### 其他全局参数 + +- `--ca` 指定 PEM 格式的受信任 CA 的证书文件路径。 +- `--cert` 指定 PEM 格式的 SSL 证书文件路径。 +- `--key` 指定 PEM 格式的 SSL 证书密钥文件路径。 +- `--status-addr` 指定 BR metric 信息。 + +### 功能介绍 + +目前,BR 包含以下子命令,各个子命令的具体用法可以使用 `br SUBCOMMAND --help` 获取使用帮助: + +* `br backup` 备份集群 +* `br restore` 恢复集群 +* `br meta` 查看备份与集群的元信息 + +### 备份使用举例 + +以备份集群为例: + +通过 `br backup -h` 可以获取这个子命令的使用帮助。backup 有两个子命令,full 和 table。 +full 用来备份整个数据库,table 用来备份指定的单个表。 + +#### full 命令 + +同样可以通过 `br backup full -h` 或 `br backup full --help` 来获取子命令 +full 的使用帮助。 + +##### 基本用法 + +例:将集群数据备份到各个 tikv 节点的 `/tmp/backup` 路径, + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 backup full \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backupfull.log +``` + +上述命令限制了 **每个 TiKV** 执行备份任务的并发数上限和速度上限,同时把 BR 的 log 写到 +`backupfull.log` 文件中。 + +备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后, +BR 为了确保数据安全性,还会校验备份数据。 + +进度条效果如下, + +```shell +br --pd ${PDIP}:2379 backup full + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backupfull.log +Full Backup <---------↖................................................> 17.12%. +``` + +#### table 命令 + +同样可以通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 +table 的使用帮助。 + +##### 基本用法 + +例:将表 `test.usertable` 备份到各个 tikv 节点的 `/tmp/backup` 路径, + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 backup table \ + --db test \ + --table usertable \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backuptable.log +``` + +table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来指定数据库名和表名, +其余参数含义一致。 + +备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后, +BR 为了确保数据安全性,还会校验备份数据。 + +进度条效果如下, + +```shell +br --pd ${PDIP}:2379 backup table \ + --db test \ + --table usertable \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backuptable.log +Table Backup <---------↖...............................................> 17.12%. +``` + +### 恢复使用举例 + +以恢复集群为例: + +通过 `br restore -h` 可以获取这个子命令的使用帮助。restore 有三个子命令, +full,db 和 table。full 用来备份整个数据库,db 用来恢复指定的数据库,table 用来备份指定的单个表。 + +#### full 命令 + +同样可以通过 `br restore full -h` 或 `br restore full --help` 来获取子命令 +full 的使用帮助。 + +##### 基本用法 + +例:将 `/tmp/backup` 路径中备份数据 **全部** 恢复到集群中 , + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 restore full \ + --storage "local:///tmp/backup" \ + --connect "root:@tcp(${TiDBIP}:4000)/" \ + --log-file restorefull.log +``` + +上述命令 `--connect` 指定了需要恢复的集群地址,同时把 BR 的 log 写到 `restorefull.log` +文件中。 + +恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后, +BR 为了确保数据安全性,还会校验恢复数据。 + +进度条效果如下, + +```shell +br --pd ${PDIP}:2379 restore full \ + --storage "local:///tmp/backup" \ + --connect "root:@tcp(${TiDBIP}:4000)/" \ + --log-file restorefull.log +Full Restore <---------↖...............................................> 17.12%. +``` + +#### db 命令 + +同样可以通过 `br restore db -h` 或 `br restore db --help` 来获取子命令 +db 的使用帮助。 + +##### 基本用法 + +例:将 `/tmp/backup` 路径中备份数据中的 **某个数据库** 恢复到集群中 , + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 restore db \ + --db "test" \ + --storage "local:///tmp/backup" \ + --connect "root:@tcp(${TiDBIP}:4000)/" \ + --log-file restorefull.log +``` + +上述命令 `--db` 指定了需要恢复的数据库名字,其余参数含义与 retstore full 一致。 + +#### table 命令 + +同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取子命令 +table 的使用帮助。 + +##### 基本用法 + +例:将 `/tmp/backup` 路径中备份数据中的 **某个数据库** 恢复到集群中 , + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 restore db \ + --db "test" \ + --table "usertable" \ + --storage "local:///tmp/backup" \ + --connect "root:@tcp(${TiDBIP}:4000)/" \ + --log-file restorefull.log +``` + +上述命令 `--table` 指定了需要恢复的表名字,其余参数含义与 retore db 一致。 + + +### 查看备份元信息举例 + +通过 `br meta -h` 可以获取这个子命令的使用帮助。meta 有一个子命令,checksum 用来 +校验备份数据是否完整。 + +#### checksum 命令 + +同样可以通过 `br meta checksum -h` 或 `br meta checksum --help` 来获取子命令 +checksum 的使用帮助。 + +##### 基本用法 + +例:校验 `/tmp/backup` 路径中备份数据是否完整, + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 meta checksum \ + --storage "local:///tmp/backup" \ + --log-file checksum.log +``` + +上述命令 `--storage` 指定了需要校验的备份数据地址,同时把 BR 的 log 写到 `checksum.log` +文件中。 + +## 最佳实践 + +- 我们推荐在 `-s` 指定的备份路径上挂载一个共享存储,比如 NFS。这样能方便收集和管理备份。 +- 在使用共享存储时,我们推荐使用高吞吐的存储硬件,存储的吞吐限制了备份/恢复的速度。 +- 我们推荐在业务低峰起执行备份,这样能最大程度地减少对业务的影响。 diff --git a/media/br-arch.png b/media/br-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..1c53beb4c89ed775780bc02cf5be5f500f932c4b GIT binary patch literal 75987 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%0A|?fNxgDnaBP7kG925G(s3R%;aN)D^!ToJi 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 literal 0 HcmV?d00001 From 1dd85937b5bdc7b6a4f1028ca539f146138774f1 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Thu, 7 Nov 2019 14:15:12 +0800 Subject: [PATCH 02/20] address lint Signed-off-by: Neil Shen --- dev/reference/tools/br.md | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index 437d19a1ce69..307cddcfb020 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -231,7 +231,6 @@ br --pd ${PDIP}:2379 restore db \ 上述命令 `--table` 指定了需要恢复的表名字,其余参数含义与 retore db 一致。 - ### 查看备份元信息举例 通过 `br meta -h` 可以获取这个子命令的使用帮助。meta 有一个子命令,checksum 用来 From bbdf0c2ceb287289c087729b06ff337a246357a8 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Mon, 11 Nov 2019 12:14:41 +0800 Subject: [PATCH 03/20] address comments Signed-off-by: Neil Shen --- dev/reference/tools/br.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index 307cddcfb020..ff87e82d8973 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -13,8 +13,8 @@ BR 是分布式备份恢复的命令行工具,用于管理分布式备份恢 ## 原理介绍 -BR 是管理分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后 -执行真正的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的 +BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后 +执行相应的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的 备份文件将会保存在该路径下,恢复时也会从该路径读取的相应的备份文件。 ![br-arch](/media/br-arch.png) @@ -24,30 +24,30 @@ BR 是管理分布式备份恢复的工具,它将备份和恢复操作下发 `br` 的使用由命令(包括子命令)、选项和参数组成。命令即不带 `-` 或者 `--` 的字符, 选项即带有 `-` 或者 `--` 的字符,参数即命令或选项字符后紧跟的传递给命令和选项的字符。 -如:`br --pd "$IP:2379" backup full -s "local:///tmp/backup"` -如:`br schema in mysql -n db` +如:`br --pd "${PDIP}:2379" backup full -s "local:///tmp/backup"` * backup: 命令 * full: backup 的子命令 * -s/--storage: 备份保存的路径 * `"local:///tmp/backup"`: -s 的参数,保存的路径为本地磁盘的 `/tmp/backup`。 * --pd: PD 服务地址 -* `"$IP:2379"`: --pd 的参数 +* `"${PDIP}:2379"`: --pd 的参数 ### 获取帮助 -`br -h/--help` 用于获取帮助信息。br 由多层命令组成,br 及其所有子命令都可以通过 -`-h/--help` 来获取使用帮助。 +br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` 来获取使用帮助,例如 +`br backup --help`。 ### 连接 `br` 与连接相关的参数有 2 个,分别为: -- `--pd` PD 服务地址 -- `--connect` TiDB 服务地址 +- `--pd` PD 服务地址,例如 `"${PDIP}:2379"``"${PDIP}:2379"` +- `--connect` TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"` -其中 `--connect` 用于 `restore` 子命令,例如:`br restore table`。 -使用 br 备份恢复功能时必须指定这两个参数,否则会报错退出。 +其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个参数, +否则会报错退出。 +例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 ### 其他全局参数 @@ -233,8 +233,8 @@ br --pd ${PDIP}:2379 restore db \ ### 查看备份元信息举例 -通过 `br meta -h` 可以获取这个子命令的使用帮助。meta 有一个子命令,checksum 用来 -校验备份数据是否完整。 +通过 `br meta -h` 可以获取这个子命令的使用帮助。目前只支持一个子命令 `checksum`, +用来校验备份数据是否完整。 #### checksum 命令 From a8971649ecd06b06bc2d9b4f36636145d0b8eb76 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Mon, 11 Nov 2019 12:32:31 +0800 Subject: [PATCH 04/20] explain restore concurrency Signed-off-by: Neil Shen --- dev/reference/tools/br.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index ff87e82d8973..b430b7026a6b 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -169,11 +169,12 @@ full 的使用帮助。 br --pd ${PDIP}:2379 restore full \ --storage "local:///tmp/backup" \ --connect "root:@tcp(${TiDBIP}:4000)/" \ + --concurrency 128 \ --log-file restorefull.log ``` -上述命令 `--connect` 指定了需要恢复的集群地址,同时把 BR 的 log 写到 `restorefull.log` -文件中。 +上述命令 `--connect` 指定了需要恢复的集群地址,`--concurrency` 指定了这个恢复任务内部的 +子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后, BR 为了确保数据安全性,还会校验恢复数据。 From b193bacc1200f4571b41a9b8e00ce05599afff40 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 12 Nov 2019 10:26:29 +0800 Subject: [PATCH 05/20] address comments Signed-off-by: Neil Shen --- dev/reference/tools/br.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index b430b7026a6b..5a871d3a0074 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -217,12 +217,12 @@ table 的使用帮助。 ##### 基本用法 -例:将 `/tmp/backup` 路径中备份数据中的 **某个数据库** 恢复到集群中 , +例:将 `/tmp/backup` 路径中备份数据中的 **某个数据表** 恢复到集群中 , {{< copyable "shell-regular" >}} ```shell -br --pd ${PDIP}:2379 restore db \ +br --pd ${PDIP}:2379 restore table \ --db "test" \ --table "usertable" \ --storage "local:///tmp/backup" \ From ba43dcf60f963bd4be54d61558e73250b3dc017e Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 12 Nov 2019 10:36:52 +0800 Subject: [PATCH 06/20] Update dev/reference/tools/br.md Co-Authored-By: Chunzhu Li --- dev/reference/tools/br.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index 5a871d3a0074..4fbff15d5cea 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -152,7 +152,7 @@ Table Backup <---------↖...............................................> 17.12 以恢复集群为例: 通过 `br restore -h` 可以获取这个子命令的使用帮助。restore 有三个子命令, -full,db 和 table。full 用来备份整个数据库,db 用来恢复指定的数据库,table 用来备份指定的单个表。 +full,db 和 table。full 用来恢复整个数据库,db 用来恢复指定的数据库,table 用来恢复指定的单个表。 #### full 命令 From 765ea99ef5ae778e5ea4d3c619d134aa766bd27d Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 12 Nov 2019 17:42:25 +0800 Subject: [PATCH 07/20] address comments Signed-off-by: Neil Shen --- dev/reference/tools/br.md | 85 +++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index 4fbff15d5cea..dcac9ea99272 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -5,17 +5,21 @@ category: reference # BR 使用说明 -BR 是分布式备份恢复的命令行工具,用于管理分布式备份恢复。 +Backup and Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具。本文档简单介绍了 BR 的工作原理和它的使用方法。 -如果通过 Ansible 部署集群,则对应的 `tidb-ansible/resources/bin` 目录下会存在 `br` -二进制文件。如果使用二进制文件部署集群,bin 目录下会包含 `br` 文件及 `tidb-server`、 -`pd-server`、以及 `tikv-server` 等其他文件。 +## 功能介绍 + +目前,BR 包含以下命令,各个命令的具体用法可以使用 `br SUBCOMMAND --help` 获取使用帮助: + +* `br backup` 备份 TiDB 集群 +* `br restore` 恢复 TiDB 集群 +* `br meta` 查看备份数据的元信息 ## 原理介绍 BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后 执行相应的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的 -备份文件将会保存在该路径下,恢复时也会从该路径读取的相应的备份文件。 +备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 ![br-arch](/media/br-arch.png) @@ -56,24 +60,14 @@ br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` - `--key` 指定 PEM 格式的 SSL 证书密钥文件路径。 - `--status-addr` 指定 BR metric 信息。 -### 功能介绍 - -目前,BR 包含以下子命令,各个子命令的具体用法可以使用 `br SUBCOMMAND --help` 获取使用帮助: - -* `br backup` 备份集群 -* `br restore` 恢复集群 -* `br meta` 查看备份与集群的元信息 - ### 备份使用举例 -以备份集群为例: - -通过 `br backup -h` 可以获取这个子命令的使用帮助。backup 有两个子命令,full 和 table。 +我们可以用 `br backup` 命令来备份 TiDB 集群。backup 有两个子命令,full 和 table。 full 用来备份整个数据库,table 用来备份指定的单个表。 -#### full 命令 +#### full 子命令 -同样可以通过 `br backup full -h` 或 `br backup full --help` 来获取子命令 +我们可以通过 `br backup full -h` 或 `br backup full --help` 来获取子命令 full 的使用帮助。 ##### 基本用法 @@ -107,7 +101,7 @@ br --pd ${PDIP}:2379 backup full Full Backup <---------↖................................................> 17.12%. ``` -#### table 命令 +#### table 子命令 同样可以通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 table 的使用帮助。 @@ -134,27 +128,12 @@ table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来 备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后, BR 为了确保数据安全性,还会校验备份数据。 -进度条效果如下, - -```shell -br --pd ${PDIP}:2379 backup table \ - --db test \ - --table usertable \ - --storage "local:///tmp/backup" \ - --ratelimit 120 \ - --concurrency 4 \ - --log-file backuptable.log -Table Backup <---------↖...............................................> 17.12%. -``` - ### 恢复使用举例 -以恢复集群为例: - -通过 `br restore -h` 可以获取这个子命令的使用帮助。restore 有三个子命令, +我们可以用 `br restore` 命令来恢复 TiDB 集群。restore 有三个子命令, full,db 和 table。full 用来恢复整个数据库,db 用来恢复指定的数据库,table 用来恢复指定的单个表。 -#### full 命令 +#### full 子命令 同样可以通过 `br restore full -h` 或 `br restore full --help` 来获取子命令 full 的使用帮助。 @@ -189,7 +168,7 @@ br --pd ${PDIP}:2379 restore full \ Full Restore <---------↖...............................................> 17.12%. ``` -#### db 命令 +#### db 子命令 同样可以通过 `br restore db -h` 或 `br restore db --help` 来获取子命令 db 的使用帮助。 @@ -210,7 +189,7 @@ br --pd ${PDIP}:2379 restore db \ 上述命令 `--db` 指定了需要恢复的数据库名字,其余参数含义与 retstore full 一致。 -#### table 命令 +#### table 子命令 同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取子命令 table 的使用帮助。 @@ -237,7 +216,7 @@ br --pd ${PDIP}:2379 restore table \ 通过 `br meta -h` 可以获取这个子命令的使用帮助。目前只支持一个子命令 `checksum`, 用来校验备份数据是否完整。 -#### checksum 命令 +#### checksum 子命令 同样可以通过 `br meta checksum -h` 或 `br meta checksum --help` 来获取子命令 checksum 的使用帮助。 @@ -262,3 +241,31 @@ br --pd ${PDIP}:2379 meta checksum \ - 我们推荐在 `-s` 指定的备份路径上挂载一个共享存储,比如 NFS。这样能方便收集和管理备份。 - 在使用共享存储时,我们推荐使用高吞吐的存储硬件,存储的吞吐限制了备份/恢复的速度。 - 我们推荐在业务低峰起执行备份,这样能最大程度地减少对业务的影响。 + +## 注意事项 + +- TiDB 执行 DDL 期间不能执行备份。 +- 目前只支持在全新的集群上执行。 +- 当备份时间可能超过 10 分钟时,我们需要调整 GC lifetime。在备份完成后,需要将 GC lifetime 调整为默认值 10 分钟。 + + {{< copyable "sql" >}} + + ``` + mysql -h${TiDBIP} -P4000 -u${TIDB_USER} ${password_str} -Nse \ + "update mysql.tidb set variable_value='720h' where variable_name='tikv_gc_life_time'"; + ``` + +- 为了加快恢复速度,可以在恢复前,使用 pd-ctl 关闭相关的 scheduler。在恢复完成后,需要将 这些 scheduler 加回来。 + + {{< copyable "shell-regular" >}} + + ```shell + # Remove scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-hot-region-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-leader-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-region-scheduler + # Add scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-hot-region-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-leader-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-region-scheduler + ``` From 38f7193252dfd8437ef2c73906bc49deb09553ef Mon Sep 17 00:00:00 2001 From: TomShawn <1135243111@qq.com> Date: Tue, 12 Nov 2019 19:49:43 +0800 Subject: [PATCH 08/20] tools: fix format --- dev/reference/tools/br.md | 87 ++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index dcac9ea99272..a62c9250ac44 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -17,16 +17,13 @@ Backup and Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令 ## 原理介绍 -BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后 -执行相应的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的 -备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 +BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后执行相应的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 ![br-arch](/media/br-arch.png) ## 使用介绍 -`br` 的使用由命令(包括子命令)、选项和参数组成。命令即不带 `-` 或者 `--` 的字符, -选项即带有 `-` 或者 `--` 的字符,参数即命令或选项字符后紧跟的传递给命令和选项的字符。 +`br` 的使用由命令(包括子命令)、选项和参数组成。命令即不带 `-` 或者 `--` 的字符,选项即带有 `-` 或者 `--` 的字符,参数即命令或选项字符后紧跟的传递给命令和选项的字符。 如:`br --pd "${PDIP}:2379" backup full -s "local:///tmp/backup"` @@ -39,8 +36,7 @@ BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各 ### 获取帮助 -br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` 来获取使用帮助,例如 -`br backup --help`。 +br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` 来获取使用帮助,例如 `br backup --help`。 ### 连接 @@ -49,9 +45,7 @@ br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` - `--pd` PD 服务地址,例如 `"${PDIP}:2379"``"${PDIP}:2379"` - `--connect` TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"` -其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个参数, -否则会报错退出。 -例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 +其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个参数,否则会报错退出。例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 ### 其他全局参数 @@ -62,17 +56,15 @@ br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` ### 备份使用举例 -我们可以用 `br backup` 命令来备份 TiDB 集群。backup 有两个子命令,full 和 table。 -full 用来备份整个数据库,table 用来备份指定的单个表。 +我们可以用 `br backup` 命令来备份 TiDB 集群。backup 有两个子命令,full 和 table。full 用来备份整个数据库,table 用来备份指定的单个表。 #### full 子命令 -我们可以通过 `br backup full -h` 或 `br backup full --help` 来获取子命令 -full 的使用帮助。 +我们可以通过 `br backup full -h` 或 `br backup full --help` 来获取子命令 full 的使用帮助。 ##### 基本用法 -例:将集群数据备份到各个 tikv 节点的 `/tmp/backup` 路径, +例:将集群数据备份到各个 tikv 节点的 `/tmp/backup` 路径 {{< copyable "shell-regular" >}} @@ -84,11 +76,9 @@ br --pd ${PDIP}:2379 backup full \ --log-file backupfull.log ``` -上述命令限制了 **每个 TiKV** 执行备份任务的并发数上限和速度上限,同时把 BR 的 log 写到 -`backupfull.log` 文件中。 +上述命令限制了 **每个 TiKV** 执行备份任务的并发数上限和速度上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 -备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后, -BR 为了确保数据安全性,还会校验备份数据。 +备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 进度条效果如下, @@ -103,12 +93,11 @@ Full Backup <---------↖................................................> 17.12 #### table 子命令 -同样可以通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 -table 的使用帮助。 +同样可以通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 table 的使用帮助。 ##### 基本用法 -例:将表 `test.usertable` 备份到各个 tikv 节点的 `/tmp/backup` 路径, +例:将表 `test.usertable` 备份到各个 tikv 节点的 `/tmp/backup` 路径 {{< copyable "shell-regular" >}} @@ -122,25 +111,21 @@ br --pd ${PDIP}:2379 backup table \ --log-file backuptable.log ``` -table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来指定数据库名和表名, -其余参数含义一致。 +table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来指定数据库名和表名,其余参数含义一致。 -备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后, -BR 为了确保数据安全性,还会校验备份数据。 +备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 ### 恢复使用举例 -我们可以用 `br restore` 命令来恢复 TiDB 集群。restore 有三个子命令, -full,db 和 table。full 用来恢复整个数据库,db 用来恢复指定的数据库,table 用来恢复指定的单个表。 +我们可以用 `br restore` 命令来恢复 TiDB 集群。restore 有三个子命令,full,db 和 table。full 用来恢复整个数据库,db 用来恢复指定的数据库,table 用来恢复指定的单个表。 #### full 子命令 -同样可以通过 `br restore full -h` 或 `br restore full --help` 来获取子命令 -full 的使用帮助。 +同样可以通过 `br restore full -h` 或 `br restore full --help` 来获取子命令 full 的使用帮助。 ##### 基本用法 -例:将 `/tmp/backup` 路径中备份数据 **全部** 恢复到集群中 , +例:将 `/tmp/backup` 路径中备份数据 **全部** 恢复到集群中 {{< copyable "shell-regular" >}} @@ -152,13 +137,11 @@ br --pd ${PDIP}:2379 restore full \ --log-file restorefull.log ``` -上述命令 `--connect` 指定了需要恢复的集群地址,`--concurrency` 指定了这个恢复任务内部的 -子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 +上述命令 `--connect` 指定了需要恢复的集群地址,`--concurrency` 指定了这个恢复任务内部的子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 -恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后, -BR 为了确保数据安全性,还会校验恢复数据。 +恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。 -进度条效果如下, +进度条效果如下: ```shell br --pd ${PDIP}:2379 restore full \ @@ -170,12 +153,11 @@ Full Restore <---------↖...............................................> 17.12 #### db 子命令 -同样可以通过 `br restore db -h` 或 `br restore db --help` 来获取子命令 -db 的使用帮助。 +同样可以通过 `br restore db -h` 或 `br restore db --help` 来获取子命令 db 的使用帮助。 ##### 基本用法 -例:将 `/tmp/backup` 路径中备份数据中的 **某个数据库** 恢复到集群中 , +例:将 `/tmp/backup` 路径中备份数据中的 **某个数据库** 恢复到集群中 {{< copyable "shell-regular" >}} @@ -191,12 +173,11 @@ br --pd ${PDIP}:2379 restore db \ #### table 子命令 -同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取子命令 -table 的使用帮助。 +同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取子命令 table 的使用帮助。 ##### 基本用法 -例:将 `/tmp/backup` 路径中备份数据中的 **某个数据表** 恢复到集群中 , +例:将 `/tmp/backup` 路径中备份数据中的 **某个数据表** 恢复到集群中 {{< copyable "shell-regular" >}} @@ -213,17 +194,15 @@ br --pd ${PDIP}:2379 restore table \ ### 查看备份元信息举例 -通过 `br meta -h` 可以获取这个子命令的使用帮助。目前只支持一个子命令 `checksum`, -用来校验备份数据是否完整。 +通过 `br meta -h` 可以获取这个子命令的使用帮助。目前只支持一个子命令 `checksum`,用来校验备份数据是否完整。 #### checksum 子命令 -同样可以通过 `br meta checksum -h` 或 `br meta checksum --help` 来获取子命令 -checksum 的使用帮助。 +同样可以通过 `br meta checksum -h` 或 `br meta checksum --help` 来获取子命令 checksum 的使用帮助。 ##### 基本用法 -例:校验 `/tmp/backup` 路径中备份数据是否完整, +例:校验 `/tmp/backup` 路径中备份数据是否完整 {{< copyable "shell-regular" >}} @@ -233,8 +212,7 @@ br --pd ${PDIP}:2379 meta checksum \ --log-file checksum.log ``` -上述命令 `--storage` 指定了需要校验的备份数据地址,同时把 BR 的 log 写到 `checksum.log` -文件中。 +上述命令 `--storage` 指定了需要校验的备份数据地址,同时把 BR 的 log 写到 `checksum.log` 文件中。 ## 最佳实践 @@ -257,14 +235,21 @@ br --pd ${PDIP}:2379 meta checksum \ - 为了加快恢复速度,可以在恢复前,使用 pd-ctl 关闭相关的 scheduler。在恢复完成后,需要将 这些 scheduler 加回来。 + 关闭 scheduler: + {{< copyable "shell-regular" >}} ```shell - # Remove scheduler ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-hot-region-scheduler ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-leader-scheduler ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-region-scheduler - # Add scheduler + ``` + + 添加 scheduler: + + {{< copyable "shell-regular" >}} + + ```shell ./pd-ctl -u ${PDIP}:2379 scheduler add balance-hot-region-scheduler ./pd-ctl -u ${PDIP}:2379 scheduler add balance-leader-scheduler ./pd-ctl -u ${PDIP}:2379 scheduler add balance-region-scheduler From b76c282b10179c38b5dd19e29138a1bb478be843 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 12 Nov 2019 20:27:36 +0800 Subject: [PATCH 09/20] remove meta command Signed-off-by: Neil Shen --- dev/reference/tools/br.md | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index a62c9250ac44..46a89586a900 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -13,7 +13,6 @@ Backup and Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令 * `br backup` 备份 TiDB 集群 * `br restore` 恢复 TiDB 集群 -* `br meta` 查看备份数据的元信息 ## 原理介绍 @@ -40,14 +39,14 @@ br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` ### 连接 -`br` 与连接相关的参数有 2 个,分别为: +`br` 与连接相关的选项有 2 个,分别为: - `--pd` PD 服务地址,例如 `"${PDIP}:2379"``"${PDIP}:2379"` - `--connect` TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"` -其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个参数,否则会报错退出。例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 +其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个选项,否则会报错退出。例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 -### 其他全局参数 +### 其他全局选项 - `--ca` 指定 PEM 格式的受信任 CA 的证书文件路径。 - `--cert` 指定 PEM 格式的 SSL 证书文件路径。 @@ -111,7 +110,7 @@ br --pd ${PDIP}:2379 backup table \ --log-file backuptable.log ``` -table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来指定数据库名和表名,其余参数含义一致。 +table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来指定数据库名和表名,其余选项含义一致。 备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 @@ -169,7 +168,7 @@ br --pd ${PDIP}:2379 restore db \ --log-file restorefull.log ``` -上述命令 `--db` 指定了需要恢复的数据库名字,其余参数含义与 retstore full 一致。 +上述命令 `--db` 指定了需要恢复的数据库名字,其余选项含义与 retstore full 一致。 #### table 子命令 @@ -190,29 +189,7 @@ br --pd ${PDIP}:2379 restore table \ --log-file restorefull.log ``` -上述命令 `--table` 指定了需要恢复的表名字,其余参数含义与 retore db 一致。 - -### 查看备份元信息举例 - -通过 `br meta -h` 可以获取这个子命令的使用帮助。目前只支持一个子命令 `checksum`,用来校验备份数据是否完整。 - -#### checksum 子命令 - -同样可以通过 `br meta checksum -h` 或 `br meta checksum --help` 来获取子命令 checksum 的使用帮助。 - -##### 基本用法 - -例:校验 `/tmp/backup` 路径中备份数据是否完整 - -{{< copyable "shell-regular" >}} - -```shell -br --pd ${PDIP}:2379 meta checksum \ - --storage "local:///tmp/backup" \ - --log-file checksum.log -``` - -上述命令 `--storage` 指定了需要校验的备份数据地址,同时把 BR 的 log 写到 `checksum.log` 文件中。 +上述命令 `--table` 指定了需要恢复的表名字,其余选项含义与 retore db 一致。 ## 最佳实践 From 6001c988cbb26d27378c7138e7111d8ca90b87f0 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Thu, 14 Nov 2019 12:15:07 +0800 Subject: [PATCH 10/20] move br to backup-and-restore Signed-off-by: Neil Shen --- dev/TOC.md | 3 +- dev/how-to/maintain/backup-and-restore/br.md | 233 ++++++++++++++++++ .../mydumper-loader.md} | 4 +- dev/reference/tools/br.md | 4 +- 4 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 dev/how-to/maintain/backup-and-restore/br.md rename dev/how-to/maintain/{backup-and-restore.md => backup-and-restore/mydumper-loader.md} (95%) diff --git a/dev/TOC.md b/dev/TOC.md index 0852ccbcd6a7..c69a80a64e7f 100644 --- a/dev/TOC.md +++ b/dev/TOC.md @@ -59,7 +59,8 @@ - [从 CSV 迁移](/dev/reference/tools/tidb-lightning/csv.md) + 运维 - [Ansible 常见运维操作](/dev/how-to/maintain/ansible-operations.md) - + [备份与恢复](/dev/how-to/maintain/backup-and-restore.md) + - [使用 mydumper/loader 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/mydumper-loader.md) + - [使用 BR 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/br.md) - [定位慢查询](/dev/how-to/maintain/identify-slow-queries.md) + 扩容缩容 - [使用 Ansible 扩容缩容](/dev/how-to/scale/with-ansible.md) diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md new file mode 100644 index 000000000000..fb475aeac3b9 --- /dev/null +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -0,0 +1,233 @@ +--- +title: 使用 BR 进行备份与恢复 +category: reference +--- + +# BR 使用说明 + +Backup and Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具。本文档简单介绍了 BR 的工作原理和它的使用方法。 + +## 功能介绍 + +目前,BR 包含以下命令,各个命令的具体用法可以使用 `br SUBCOMMAND --help` 获取使用帮助: + +* `br backup` 备份 TiDB 集群 +* `br restore` 恢复 TiDB 集群 + +## 原理介绍 + +BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后执行相应的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 + +![br-arch](/media/br-arch.png) + +## 使用介绍 + +`br` 的使用由命令(包括子命令)、选项和参数组成。命令即不带 `-` 或者 `--` 的字符,选项即带有 `-` 或者 `--` 的字符,参数即命令或选项字符后紧跟的传递给命令和选项的字符。 + +如:`br --pd "${PDIP}:2379" backup full -s "local:///tmp/backup"` + +* backup: 命令 +* full: backup 的子命令 +* -s/--storage: 备份保存的路径 +* `"local:///tmp/backup"`: -s 的参数,保存的路径为本地磁盘的 `/tmp/backup`。 +* --pd: PD 服务地址 +* `"${PDIP}:2379"`: --pd 的参数 + +### 获取帮助 + +br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` 来获取使用帮助,例如 `br backup --help`。 + +### 连接 + +`br` 与连接相关的选项有 2 个,分别为: + +- `--pd` PD 服务地址,例如 `"${PDIP}:2379"``"${PDIP}:2379"` +- `--connect` TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"` + +其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个选项,否则会报错退出。例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 + +### 其他全局选项 + +- `--ca` 指定 PEM 格式的受信任 CA 的证书文件路径。 +- `--cert` 指定 PEM 格式的 SSL 证书文件路径。 +- `--key` 指定 PEM 格式的 SSL 证书密钥文件路径。 +- `--status-addr` 指定 BR metric 信息。 + +### 备份使用举例 + +我们可以用 `br backup` 命令来备份 TiDB 集群。backup 有两个子命令,full 和 table。full 用来备份整个数据库,table 用来备份指定的单个表。 + +#### full 子命令 + +我们可以通过 `br backup full -h` 或 `br backup full --help` 来获取子命令 full 的使用帮助。 + +##### 基本用法 + +例:将集群数据备份到各个 tikv 节点的 `/tmp/backup` 路径 + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 backup full \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backupfull.log +``` + +上述命令限制了 **每个 TiKV** 执行备份任务的并发数上限和速度上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 + +备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 + +进度条效果如下, + +```shell +br --pd ${PDIP}:2379 backup full + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backupfull.log +Full Backup <---------↖................................................> 17.12%. +``` + +#### table 子命令 + +同样可以通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 table 的使用帮助。 + +##### 基本用法 + +例:将表 `test.usertable` 备份到各个 tikv 节点的 `/tmp/backup` 路径 + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 backup table \ + --db test \ + --table usertable \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backuptable.log +``` + +table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来指定数据库名和表名,其余选项含义一致。 + +备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 + +### 恢复使用举例 + +我们可以用 `br restore` 命令来恢复 TiDB 集群。restore 有三个子命令,full,db 和 table。full 用来恢复整个数据库,db 用来恢复指定的数据库,table 用来恢复指定的单个表。 + +#### full 子命令 + +同样可以通过 `br restore full -h` 或 `br restore full --help` 来获取子命令 full 的使用帮助。 + +##### 基本用法 + +例:将 `/tmp/backup` 路径中备份数据 **全部** 恢复到集群中 + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 restore full \ + --storage "local:///tmp/backup" \ + --connect "root:@tcp(${TiDBIP}:4000)/" \ + --concurrency 128 \ + --log-file restorefull.log +``` + +上述命令 `--connect` 指定了需要恢复的集群地址,`--concurrency` 指定了这个恢复任务内部的子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 + +恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。 + +进度条效果如下: + +```shell +br --pd ${PDIP}:2379 restore full \ + --storage "local:///tmp/backup" \ + --connect "root:@tcp(${TiDBIP}:4000)/" \ + --log-file restorefull.log +Full Restore <---------↖...............................................> 17.12%. +``` + +#### db 子命令 + +同样可以通过 `br restore db -h` 或 `br restore db --help` 来获取子命令 db 的使用帮助。 + +##### 基本用法 + +例:将 `/tmp/backup` 路径中备份数据中的 **某个数据库** 恢复到集群中 + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 restore db \ + --db "test" \ + --storage "local:///tmp/backup" \ + --connect "root:@tcp(${TiDBIP}:4000)/" \ + --log-file restorefull.log +``` + +上述命令 `--db` 指定了需要恢复的数据库名字,其余选项含义与 retstore full 一致。 + +#### table 子命令 + +同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取子命令 table 的使用帮助。 + +##### 基本用法 + +例:将 `/tmp/backup` 路径中备份数据中的 **某个数据表** 恢复到集群中 + +{{< copyable "shell-regular" >}} + +```shell +br --pd ${PDIP}:2379 restore table \ + --db "test" \ + --table "usertable" \ + --storage "local:///tmp/backup" \ + --connect "root:@tcp(${TiDBIP}:4000)/" \ + --log-file restorefull.log +``` + +上述命令 `--table` 指定了需要恢复的表名字,其余选项含义与 retore db 一致。 + +## 最佳实践 + +- 我们推荐在 `-s` 指定的备份路径上挂载一个共享存储,比如 NFS。这样能方便收集和管理备份。 +- 在使用共享存储时,我们推荐使用高吞吐的存储硬件,存储的吞吐限制了备份/恢复的速度。 +- 我们推荐在业务低峰起执行备份,这样能最大程度地减少对业务的影响。 + +## 注意事项 + +- TiDB 执行 DDL 期间不能执行备份。 +- 目前只支持在全新的集群上执行。 +- 当备份时间可能超过 10 分钟时,我们需要调整 GC lifetime。在备份完成后,需要将 GC lifetime 调整为默认值 10 分钟。 + + {{< copyable "sql" >}} + + ``` + mysql -h${TiDBIP} -P4000 -u${TIDB_USER} ${password_str} -Nse \ + "update mysql.tidb set variable_value='720h' where variable_name='tikv_gc_life_time'"; + ``` + +- 为了加快恢复速度,可以在恢复前,使用 pd-ctl 关闭相关的 scheduler。在恢复完成后,需要将 这些 scheduler 加回来。 + + 关闭 scheduler: + + {{< copyable "shell-regular" >}} + + ```shell + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-hot-region-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-leader-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-region-scheduler + ``` + + 添加 scheduler: + + {{< copyable "shell-regular" >}} + + ```shell + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-hot-region-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-leader-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-region-scheduler + ``` diff --git a/dev/how-to/maintain/backup-and-restore.md b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md similarity index 95% rename from dev/how-to/maintain/backup-and-restore.md rename to dev/how-to/maintain/backup-and-restore/mydumper-loader.md index 176dc2f2921d..565b2a15ecb8 100644 --- a/dev/how-to/maintain/backup-and-restore.md +++ b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md @@ -1,11 +1,11 @@ --- -title: 备份与恢复 +title: 使用 mydumper/loader 进行备份与恢复 category: how-to --- # 备份与恢复 -本文档将详细介绍如何对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/dev/reference/tidb-binlog/overview.md)。 +本文档将详细介绍如何使用 mydumper/loader 对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/dev/reference/tidb-binlog/overview.md)。 这里我们假定 TiDB 服务信息如下: diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md index 46a89586a900..0adcc1aaec8a 100644 --- a/dev/reference/tools/br.md +++ b/dev/reference/tools/br.md @@ -41,7 +41,7 @@ br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` `br` 与连接相关的选项有 2 个,分别为: -- `--pd` PD 服务地址,例如 `"${PDIP}:2379"``"${PDIP}:2379"` +- `--pd` PD 服务地址,例如 `"${PDIP}:2379"` - `--connect` TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"` 其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个选项,否则会报错退出。例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 @@ -200,7 +200,7 @@ br --pd ${PDIP}:2379 restore table \ ## 注意事项 - TiDB 执行 DDL 期间不能执行备份。 -- 目前只支持在全新的集群上执行。 +- 目前只支持在空集群上执行恢复。 - 当备份时间可能超过 10 分钟时,我们需要调整 GC lifetime。在备份完成后,需要将 GC lifetime 调整为默认值 10 分钟。 {{< copyable "sql" >}} From 3260da2e7781bf167efaa8bbfb232067454efa7b Mon Sep 17 00:00:00 2001 From: TomShawn <1135243111@qq.com> Date: Thu, 14 Nov 2019 17:52:34 +0800 Subject: [PATCH 11/20] maintain: restructure content and refine wording --- dev/how-to/maintain/backup-and-restore/br.md | 148 +++++++++---------- 1 file changed, 69 insertions(+), 79 deletions(-) diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index fb475aeac3b9..bd182f8dd7d5 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -3,67 +3,71 @@ title: 使用 BR 进行备份与恢复 category: reference --- -# BR 使用说明 +# 使用 BR 进行备份与恢复 -Backup and Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具。本文档简单介绍了 BR 的工作原理和它的使用方法。 +Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行备份和恢复,尤其适用于大数据量的场景。本文档介绍了 BR 的工作原理、命令行描述以及详细的备份恢复用例。 -## 功能介绍 - -目前,BR 包含以下命令,各个命令的具体用法可以使用 `br SUBCOMMAND --help` 获取使用帮助: - -* `br backup` 备份 TiDB 集群 -* `br restore` 恢复 TiDB 集群 - -## 原理介绍 +## 工作原理 BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后执行相应的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 ![br-arch](/media/br-arch.png) -## 使用介绍 +## BR 命令行描述 -`br` 的使用由命令(包括子命令)、选项和参数组成。命令即不带 `-` 或者 `--` 的字符,选项即带有 `-` 或者 `--` 的字符,参数即命令或选项字符后紧跟的传递给命令和选项的字符。 +`br` 命令行是由命令(包括子命令)、选项和参数组成的。命令即不带 `-` 或者 `--` 的字符。选项即带有 `-` 或者 `--` 的字符。参数即命令或选项字符后紧跟的、传递给命令和选项的字符。 -如:`br --pd "${PDIP}:2379" backup full -s "local:///tmp/backup"` +以下是一条完整的 `br` 命令行: -* backup: 命令 -* full: backup 的子命令 -* -s/--storage: 备份保存的路径 -* `"local:///tmp/backup"`: -s 的参数,保存的路径为本地磁盘的 `/tmp/backup`。 -* --pd: PD 服务地址 -* `"${PDIP}:2379"`: --pd 的参数 +`br --pd "${PDIP}:2379" backup full -s "local:///tmp/backup"` -### 获取帮助 +命令行各部分的解释如下: -br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` 来获取使用帮助,例如 `br backup --help`。 +* `backup`:命令 +* `full`:`backup` 的子命令 +* `-s` 或 `--storage`:备份保存的路径 +* `"local:///tmp/backup"`:`-s` 的参数,保存的路径为本地磁盘的 `/tmp/backup` +* `--pd`:PD 服务地址 +* `"${PDIP}:2379"`:`--pd` 的参数 -### 连接 +### 命令和子命令 -`br` 与连接相关的选项有 2 个,分别为: +BR 由多层命令组成。目前,BR 包含 `backup`,`restore` 和 `meta` 三个命令。 -- `--pd` PD 服务地址,例如 `"${PDIP}:2379"``"${PDIP}:2379"` -- `--connect` TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"` +* `br backup` 用于备份 TiDB 集群 +* `br restore` 用于恢复 TiDB 集群 +* `br meta` 用于查看备份集群的元信息 -其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个选项,否则会报错退出。例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 +BR 还包含以下三个子命令: -### 其他全局选项 +* `full`:可用于备份或恢复全部数据。 +* `db`:可用于备份或恢复集群中的指定数据库。 +* `table`:可用于备份或恢复集群指定数据库中的单张表。 -- `--ca` 指定 PEM 格式的受信任 CA 的证书文件路径。 -- `--cert` 指定 PEM 格式的 SSL 证书文件路径。 -- `--key` 指定 PEM 格式的 SSL 证书密钥文件路径。 -- `--status-addr` 指定 BR metric 信息。 +### 常用选项 -### 备份使用举例 +* `--pd`:用于连接的选项,表示 PD 服务地址,例如 `"${PDIP}:2379"`。 +* `--connect`:用于连接的选项,表示 TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"`。 -我们可以用 `br backup` 命令来备份 TiDB 集群。backup 有两个子命令,full 和 table。full 用来备份整个数据库,table 用来备份指定的单个表。 + > **注意:** + > + > 该选项只可用在 `restore` 命令中。使用 BR 恢复集群时必须指定该选项,否则 BR 会报错退出。用例:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 -#### full 子命令 +* `-h/--help`:获取所有命令和子命令的使用帮助。例如 `br backup --help`。 +* `--ca`:指定 PEM 格式的受信任 CA 的证书文件路径。 +* `--cert`:指定 PEM 格式的 SSL 证书文件路径。 +* `--key`:指定 PEM 格式的 SSL 证书密钥文件路径。 +* `--status-addr`:指定 BR metric 信息。 -我们可以通过 `br backup full -h` 或 `br backup full --help` 来获取子命令 full 的使用帮助。 +## 使用说明 -##### 基本用法 +### 备份集群 -例:将集群数据备份到各个 tikv 节点的 `/tmp/backup` 路径 +#### 备份全部集群数据 + +要备份全部集群数据,可使用 `br backup full` 命令。该命令的使用帮助可以通过 `br backup full -h` 或 `br backup full --help` 来获取。 + +用例:将所有集群数据备份到各个 TiKV 节点的 `/tmp/backup` 路径 {{< copyable "shell-regular" >}} @@ -75,11 +79,9 @@ br --pd ${PDIP}:2379 backup full \ --log-file backupfull.log ``` -上述命令限制了 **每个 TiKV** 执行备份任务的并发数上限和速度上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 - -备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 +以上命令通过 `--ratelimit` 和 `--concurrency` 选项限制了 **每个 TiKV** 执行备份任务的并发数上限和速度上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 -进度条效果如下, +备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。进度条效果如下: ```shell br --pd ${PDIP}:2379 backup full @@ -90,13 +92,11 @@ br --pd ${PDIP}:2379 backup full Full Backup <---------↖................................................> 17.12%. ``` -#### table 子命令 +#### 备份单张表的数据 -同样可以通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 table 的使用帮助。 +要备份集群中指定单张表的数据,可使用 `br backup table` 命令。同样可通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 `table` 的使用帮助。 -##### 基本用法 - -例:将表 `test.usertable` 备份到各个 tikv 节点的 `/tmp/backup` 路径 +用例:将表 `test.usertable` 备份到各个 TiKV 节点的 `/tmp/backup` 路径 {{< copyable "shell-regular" >}} @@ -110,21 +110,17 @@ br --pd ${PDIP}:2379 backup table \ --log-file backuptable.log ``` -table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来指定数据库名和表名,其余选项含义一致。 - -备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 - -### 恢复使用举例 +`table` 子命令有 `--db` 和 `--table` 两个选项,分别用来指定数据库名和表名,其余选项含义一致。 -我们可以用 `br restore` 命令来恢复 TiDB 集群。restore 有三个子命令,full,db 和 table。full 用来恢复整个数据库,db 用来恢复指定的数据库,table 用来恢复指定的单个表。 +备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 -#### full 子命令 +### 恢复集群 -同样可以通过 `br restore full -h` 或 `br restore full --help` 来获取子命令 full 的使用帮助。 +#### 恢复全部备份数据 -##### 基本用法 +要将全部备份数据恢复到集群中来,可使用 `br restore full` 命令。该命令的使用帮助可以通过 `br restore full -h` 或 `br restore full --help` 来获取。 -例:将 `/tmp/backup` 路径中备份数据 **全部** 恢复到集群中 +用例:将 `/tmp/backup` 路径中的全部备份数据恢复到集群中 {{< copyable "shell-regular" >}} @@ -136,11 +132,9 @@ br --pd ${PDIP}:2379 restore full \ --log-file restorefull.log ``` -上述命令 `--connect` 指定了需要恢复的集群地址,`--concurrency` 指定了这个恢复任务内部的子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 +以上命令中 `--connect` 选项指定了需要恢复的集群地址。`--concurrency` 指定了该恢复任务内部的子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 -恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。 - -进度条效果如下: +恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。进度条效果如下: ```shell br --pd ${PDIP}:2379 restore full \ @@ -150,13 +144,11 @@ br --pd ${PDIP}:2379 restore full \ Full Restore <---------↖...............................................> 17.12%. ``` -#### db 子命令 - -同样可以通过 `br restore db -h` 或 `br restore db --help` 来获取子命令 db 的使用帮助。 +#### 恢复某个数据库 -##### 基本用法 +要将备份数据中的某个数据库恢复到集群中,可以使用 `br restore db` 命令。该命令的使用帮助可以通过 `br restore db -h` 或 `br restore db --help` 来获取。 -例:将 `/tmp/backup` 路径中备份数据中的 **某个数据库** 恢复到集群中 +用例:将 `/tmp/backup` 路径中备份数据中的某个数据库恢复到集群中 {{< copyable "shell-regular" >}} @@ -168,15 +160,13 @@ br --pd ${PDIP}:2379 restore db \ --log-file restorefull.log ``` -上述命令 `--db` 指定了需要恢复的数据库名字,其余选项含义与 retstore full 一致。 - -#### table 子命令 +以上命令中 `--db` 选项指定了需要恢复的数据库名字,其余选项含义与 `restore full` 一致。 -同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取子命令 table 的使用帮助。 +#### 恢复某张数据表 -##### 基本用法 +要将备份数据中的某张数据表恢复到集群中,可以使用 `br restore table` 命令。该命令的使用帮助可以通过同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取。 -例:将 `/tmp/backup` 路径中备份数据中的 **某个数据表** 恢复到集群中 +用例:将 `/tmp/backup` 路径中备份数据中的某个数据表恢复到集群中 {{< copyable "shell-regular" >}} @@ -189,19 +179,19 @@ br --pd ${PDIP}:2379 restore table \ --log-file restorefull.log ``` -上述命令 `--table` 指定了需要恢复的表名字,其余选项含义与 retore db 一致。 +以上命令中 `--table` 选项指定了需要恢复的表名,其余选项含义与 `restore db` 一致。 ## 最佳实践 -- 我们推荐在 `-s` 指定的备份路径上挂载一个共享存储,比如 NFS。这样能方便收集和管理备份。 -- 在使用共享存储时,我们推荐使用高吞吐的存储硬件,存储的吞吐限制了备份/恢复的速度。 -- 我们推荐在业务低峰起执行备份,这样能最大程度地减少对业务的影响。 +- 推荐在 `-s` 指定的备份路径上挂载一个共享存储,例如 NFS。这样能方便收集和管理备份操作。 +- 在使用共享存储时,推荐使用高吞吐的存储硬件,因为存储的吞吐会限制了备份/恢复的速度。 +- 推荐在业务低峰时执行备份操作,这样能最大程度地减少对业务的影响。 ## 注意事项 -- TiDB 执行 DDL 期间不能执行备份。 -- 目前只支持在全新的集群上执行。 -- 当备份时间可能超过 10 分钟时,我们需要调整 GC lifetime。在备份完成后,需要将 GC lifetime 调整为默认值 10 分钟。 +- TiDB 执行 DDL 期间不能执行备份操作。 +- 目前只支持在全新的集群上执行备份和恢复操作。 +- 如果备份时间可能超过 10 分钟时,需要调整 GC lifetime。备份完成后,需要将 GC lifetime 调整为默认值 10 分钟。 {{< copyable "sql" >}} @@ -210,7 +200,7 @@ br --pd ${PDIP}:2379 restore table \ "update mysql.tidb set variable_value='720h' where variable_name='tikv_gc_life_time'"; ``` -- 为了加快恢复速度,可以在恢复前,使用 pd-ctl 关闭相关的 scheduler。在恢复完成后,需要将 这些 scheduler 加回来。 +- 为了加快数据恢复速度,可以在恢复操作前,使用 pd-ctl 关闭相关的 scheduler。恢复完成后,再重新添加这些 scheduler。 关闭 scheduler: From 6a8588cea6f9706cd39925950c718bda71986578 Mon Sep 17 00:00:00 2001 From: TomShawn <1135243111@qq.com> Date: Thu, 14 Nov 2019 18:58:18 +0800 Subject: [PATCH 12/20] maintain: refine content --- dev/how-to/maintain/backup-and-restore/br.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index bd182f8dd7d5..2469df6cd691 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -1,15 +1,16 @@ --- title: 使用 BR 进行备份与恢复 +summary: 了解如何使用 BR 工具进行集群数据备份和恢复。 category: reference --- # 使用 BR 进行备份与恢复 -Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行备份和恢复,尤其适用于大数据量的场景。本文档介绍了 BR 的工作原理、命令行描述以及详细的备份恢复用例。 +Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行数据备份和恢复。相比 Mydumper,BR 更适合大数据量的场景。本文档介绍了 BR 的工作原理、命令行描述以及详细的备份恢复用例。 ## 工作原理 -BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后执行相应的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 +BR 是分布式备份恢复的工具,它将备份和恢复操作命令下发到各个 TiKV 节点,TiKV 收到命令后执行相应的备份和恢复操作。在一次备份或恢复中,各个 TiKV 节点都会有一个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 ![br-arch](/media/br-arch.png) @@ -61,6 +62,9 @@ BR 还包含以下三个子命令: ## 使用说明 ++ 如果使用 Ansible 部署 TiDB 集群,则对应的 tidb-ansible/resources/bin 目录下会存在 br 二进制文件。 ++ 如果使用二进制文件部署 TiDB 集群,bin 目录下会包含 br 文件及 tidb-server、 pd-server、以及 tikv-server 等其他文件。 + ### 备份集群 #### 备份全部集群数据 From 4f4c8cc363b0e8fd8cc07479511222b46e8a7328 Mon Sep 17 00:00:00 2001 From: TomShawn <1135243111@qq.com> Date: Fri, 15 Nov 2019 12:02:52 +0800 Subject: [PATCH 13/20] maintain: refine headings --- dev/how-to/maintain/backup-and-restore/br.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index 2469df6cd691..9bbc6b67929a 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -60,14 +60,9 @@ BR 还包含以下三个子命令: * `--key`:指定 PEM 格式的 SSL 证书密钥文件路径。 * `--status-addr`:指定 BR metric 信息。 -## 使用说明 +## 备份集群数据 -+ 如果使用 Ansible 部署 TiDB 集群,则对应的 tidb-ansible/resources/bin 目录下会存在 br 二进制文件。 -+ 如果使用二进制文件部署 TiDB 集群,bin 目录下会包含 br 文件及 tidb-server、 pd-server、以及 tikv-server 等其他文件。 - -### 备份集群 - -#### 备份全部集群数据 +### 备份全部集群数据 要备份全部集群数据,可使用 `br backup full` 命令。该命令的使用帮助可以通过 `br backup full -h` 或 `br backup full --help` 来获取。 @@ -96,7 +91,7 @@ br --pd ${PDIP}:2379 backup full Full Backup <---------↖................................................> 17.12%. ``` -#### 备份单张表的数据 +### 备份单张表的数据 要备份集群中指定单张表的数据,可使用 `br backup table` 命令。同样可通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 `table` 的使用帮助。 @@ -118,9 +113,9 @@ br --pd ${PDIP}:2379 backup table \ 备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 -### 恢复集群 +## 恢复集群数据 -#### 恢复全部备份数据 +### 恢复全部备份数据 要将全部备份数据恢复到集群中来,可使用 `br restore full` 命令。该命令的使用帮助可以通过 `br restore full -h` 或 `br restore full --help` 来获取。 @@ -148,7 +143,7 @@ br --pd ${PDIP}:2379 restore full \ Full Restore <---------↖...............................................> 17.12%. ``` -#### 恢复某个数据库 +### 恢复某个数据库 要将备份数据中的某个数据库恢复到集群中,可以使用 `br restore db` 命令。该命令的使用帮助可以通过 `br restore db -h` 或 `br restore db --help` 来获取。 @@ -166,7 +161,7 @@ br --pd ${PDIP}:2379 restore db \ 以上命令中 `--db` 选项指定了需要恢复的数据库名字,其余选项含义与 `restore full` 一致。 -#### 恢复某张数据表 +### 恢复某张数据表 要将备份数据中的某张数据表恢复到集群中,可以使用 `br restore table` 命令。该命令的使用帮助可以通过同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取。 From ff0e57b76591495a0992d87745db0d952d6a4a3a Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Fri, 15 Nov 2019 12:26:26 +0800 Subject: [PATCH 14/20] Address comments Signed-off-by: Neil Shen --- dev/how-to/maintain/backup-and-restore/br.md | 10 +- dev/reference/tools/br.md | 233 ------------------- 2 files changed, 6 insertions(+), 237 deletions(-) delete mode 100644 dev/reference/tools/br.md diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index 9bbc6b67929a..a44658f7e603 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -33,11 +33,11 @@ BR 是分布式备份恢复的工具,它将备份和恢复操作命令下发 ### 命令和子命令 -BR 由多层命令组成。目前,BR 包含 `backup`,`restore` 和 `meta` 三个命令。 +BR 由多层命令组成。目前,BR 包含 `backup`,`restore` 和 `version` 三个命令。 * `br backup` 用于备份 TiDB 集群 * `br restore` 用于恢复 TiDB 集群 -* `br meta` 用于查看备份集群的元信息 +* `br version` 用于查看 BR 工具版本信息 BR 还包含以下三个子命令: @@ -189,8 +189,10 @@ br --pd ${PDIP}:2379 restore table \ ## 注意事项 - TiDB 执行 DDL 期间不能执行备份操作。 -- 目前只支持在全新的集群上执行备份和恢复操作。 -- 如果备份时间可能超过 10 分钟时,需要调整 GC lifetime。备份完成后,需要将 GC lifetime 调整为默认值 10 分钟。 +- 目前只支持在全新的集群上执行恢复操作。 +- 如果备份时间可能超过设定的 GC lifetime(默认 10 分钟),则需要将 GC lifetime 调大。 + + 例如,将 GC lifetime 调整为 720 小时。 {{< copyable "sql" >}} diff --git a/dev/reference/tools/br.md b/dev/reference/tools/br.md deleted file mode 100644 index 0adcc1aaec8a..000000000000 --- a/dev/reference/tools/br.md +++ /dev/null @@ -1,233 +0,0 @@ ---- -title: BR 使用说明 -category: reference ---- - -# BR 使用说明 - -Backup and Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具。本文档简单介绍了 BR 的工作原理和它的使用方法。 - -## 功能介绍 - -目前,BR 包含以下命令,各个命令的具体用法可以使用 `br SUBCOMMAND --help` 获取使用帮助: - -* `br backup` 备份 TiDB 集群 -* `br restore` 恢复 TiDB 集群 - -## 原理介绍 - -BR 是分布式备份恢复的工具,它将备份和恢复操作下发到各个 TiKV 节点,TiKV 收到命令后执行相应的备份和恢复。在一次备份或恢复中各个 TiKV 都会有个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 - -![br-arch](/media/br-arch.png) - -## 使用介绍 - -`br` 的使用由命令(包括子命令)、选项和参数组成。命令即不带 `-` 或者 `--` 的字符,选项即带有 `-` 或者 `--` 的字符,参数即命令或选项字符后紧跟的传递给命令和选项的字符。 - -如:`br --pd "${PDIP}:2379" backup full -s "local:///tmp/backup"` - -* backup: 命令 -* full: backup 的子命令 -* -s/--storage: 备份保存的路径 -* `"local:///tmp/backup"`: -s 的参数,保存的路径为本地磁盘的 `/tmp/backup`。 -* --pd: PD 服务地址 -* `"${PDIP}:2379"`: --pd 的参数 - -### 获取帮助 - -br 由多层命令组成,br 及其所有子命令都可以通过 `-h/--help` 来获取使用帮助,例如 `br backup --help`。 - -### 连接 - -`br` 与连接相关的选项有 2 个,分别为: - -- `--pd` PD 服务地址,例如 `"${PDIP}:2379"` -- `--connect` TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"` - -其中 `--connect` 只适用于 `restore` 子命令,使用 br 恢复功能时必须指定这个选项,否则会报错退出。例如:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 - -### 其他全局选项 - -- `--ca` 指定 PEM 格式的受信任 CA 的证书文件路径。 -- `--cert` 指定 PEM 格式的 SSL 证书文件路径。 -- `--key` 指定 PEM 格式的 SSL 证书密钥文件路径。 -- `--status-addr` 指定 BR metric 信息。 - -### 备份使用举例 - -我们可以用 `br backup` 命令来备份 TiDB 集群。backup 有两个子命令,full 和 table。full 用来备份整个数据库,table 用来备份指定的单个表。 - -#### full 子命令 - -我们可以通过 `br backup full -h` 或 `br backup full --help` 来获取子命令 full 的使用帮助。 - -##### 基本用法 - -例:将集群数据备份到各个 tikv 节点的 `/tmp/backup` 路径 - -{{< copyable "shell-regular" >}} - -```shell -br --pd ${PDIP}:2379 backup full \ - --storage "local:///tmp/backup" \ - --ratelimit 120 \ - --concurrency 4 \ - --log-file backupfull.log -``` - -上述命令限制了 **每个 TiKV** 执行备份任务的并发数上限和速度上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 - -备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 - -进度条效果如下, - -```shell -br --pd ${PDIP}:2379 backup full - --storage "local:///tmp/backup" \ - --ratelimit 120 \ - --concurrency 4 \ - --log-file backupfull.log -Full Backup <---------↖................................................> 17.12%. -``` - -#### table 子命令 - -同样可以通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 table 的使用帮助。 - -##### 基本用法 - -例:将表 `test.usertable` 备份到各个 tikv 节点的 `/tmp/backup` 路径 - -{{< copyable "shell-regular" >}} - -```shell -br --pd ${PDIP}:2379 backup table \ - --db test \ - --table usertable \ - --storage "local:///tmp/backup" \ - --ratelimit 120 \ - --concurrency 4 \ - --log-file backuptable.log -``` - -table 命令与 full 命令相比,多了 `--db` 和 `--table`,分别用来指定数据库名和表名,其余选项含义一致。 - -备份期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 - -### 恢复使用举例 - -我们可以用 `br restore` 命令来恢复 TiDB 集群。restore 有三个子命令,full,db 和 table。full 用来恢复整个数据库,db 用来恢复指定的数据库,table 用来恢复指定的单个表。 - -#### full 子命令 - -同样可以通过 `br restore full -h` 或 `br restore full --help` 来获取子命令 full 的使用帮助。 - -##### 基本用法 - -例:将 `/tmp/backup` 路径中备份数据 **全部** 恢复到集群中 - -{{< copyable "shell-regular" >}} - -```shell -br --pd ${PDIP}:2379 restore full \ - --storage "local:///tmp/backup" \ - --connect "root:@tcp(${TiDBIP}:4000)/" \ - --concurrency 128 \ - --log-file restorefull.log -``` - -上述命令 `--connect` 指定了需要恢复的集群地址,`--concurrency` 指定了这个恢复任务内部的子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 - -恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。 - -进度条效果如下: - -```shell -br --pd ${PDIP}:2379 restore full \ - --storage "local:///tmp/backup" \ - --connect "root:@tcp(${TiDBIP}:4000)/" \ - --log-file restorefull.log -Full Restore <---------↖...............................................> 17.12%. -``` - -#### db 子命令 - -同样可以通过 `br restore db -h` 或 `br restore db --help` 来获取子命令 db 的使用帮助。 - -##### 基本用法 - -例:将 `/tmp/backup` 路径中备份数据中的 **某个数据库** 恢复到集群中 - -{{< copyable "shell-regular" >}} - -```shell -br --pd ${PDIP}:2379 restore db \ - --db "test" \ - --storage "local:///tmp/backup" \ - --connect "root:@tcp(${TiDBIP}:4000)/" \ - --log-file restorefull.log -``` - -上述命令 `--db` 指定了需要恢复的数据库名字,其余选项含义与 retstore full 一致。 - -#### table 子命令 - -同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取子命令 table 的使用帮助。 - -##### 基本用法 - -例:将 `/tmp/backup` 路径中备份数据中的 **某个数据表** 恢复到集群中 - -{{< copyable "shell-regular" >}} - -```shell -br --pd ${PDIP}:2379 restore table \ - --db "test" \ - --table "usertable" \ - --storage "local:///tmp/backup" \ - --connect "root:@tcp(${TiDBIP}:4000)/" \ - --log-file restorefull.log -``` - -上述命令 `--table` 指定了需要恢复的表名字,其余选项含义与 retore db 一致。 - -## 最佳实践 - -- 我们推荐在 `-s` 指定的备份路径上挂载一个共享存储,比如 NFS。这样能方便收集和管理备份。 -- 在使用共享存储时,我们推荐使用高吞吐的存储硬件,存储的吞吐限制了备份/恢复的速度。 -- 我们推荐在业务低峰起执行备份,这样能最大程度地减少对业务的影响。 - -## 注意事项 - -- TiDB 执行 DDL 期间不能执行备份。 -- 目前只支持在空集群上执行恢复。 -- 当备份时间可能超过 10 分钟时,我们需要调整 GC lifetime。在备份完成后,需要将 GC lifetime 调整为默认值 10 分钟。 - - {{< copyable "sql" >}} - - ``` - mysql -h${TiDBIP} -P4000 -u${TIDB_USER} ${password_str} -Nse \ - "update mysql.tidb set variable_value='720h' where variable_name='tikv_gc_life_time'"; - ``` - -- 为了加快恢复速度,可以在恢复前,使用 pd-ctl 关闭相关的 scheduler。在恢复完成后,需要将 这些 scheduler 加回来。 - - 关闭 scheduler: - - {{< copyable "shell-regular" >}} - - ```shell - ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-hot-region-scheduler - ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-leader-scheduler - ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-region-scheduler - ``` - - 添加 scheduler: - - {{< copyable "shell-regular" >}} - - ```shell - ./pd-ctl -u ${PDIP}:2379 scheduler add balance-hot-region-scheduler - ./pd-ctl -u ${PDIP}:2379 scheduler add balance-leader-scheduler - ./pd-ctl -u ${PDIP}:2379 scheduler add balance-region-scheduler - ``` From ac48aa35556b15984774e648514d1895771cae77 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 19 Nov 2019 13:52:10 +0800 Subject: [PATCH 15/20] address comments Signed-off-by: Neil Shen --- dev/how-to/maintain/backup-and-restore/br.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index a44658f7e603..7264e0b71fcf 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -20,7 +20,7 @@ BR 是分布式备份恢复的工具,它将备份和恢复操作命令下发 以下是一条完整的 `br` 命令行: -`br --pd "${PDIP}:2379" backup full -s "local:///tmp/backup"` +`br backup full --pd "${PDIP}:2379" -s "local:///tmp/backup"` 命令行各部分的解释如下: @@ -33,7 +33,7 @@ BR 是分布式备份恢复的工具,它将备份和恢复操作命令下发 ### 命令和子命令 -BR 由多层命令组成。目前,BR 包含 `backup`,`restore` 和 `version` 三个命令。 +BR 由多层命令组成。目前,BR 包含 `backup`、`restore` 和 `version` 三个命令。 * `br backup` 用于备份 TiDB 集群 * `br restore` 用于恢复 TiDB 集群 @@ -54,11 +54,11 @@ BR 还包含以下三个子命令: > > 该选项只可用在 `restore` 命令中。使用 BR 恢复集群时必须指定该选项,否则 BR 会报错退出。用例:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 -* `-h/--help`:获取所有命令和子命令的使用帮助。例如 `br backup --help`。 +* `-h`/`--help`:获取所有命令和子命令的使用帮助。例如 `br backup --help`。 * `--ca`:指定 PEM 格式的受信任 CA 的证书文件路径。 * `--cert`:指定 PEM 格式的 SSL 证书文件路径。 * `--key`:指定 PEM 格式的 SSL 证书密钥文件路径。 -* `--status-addr`:指定 BR metric 信息。 +* `--status-addr`:指定 BR 提供 Prometheus 统计的监听地址。 ## 备份集群数据 @@ -83,7 +83,7 @@ br --pd ${PDIP}:2379 backup full \ 备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。进度条效果如下: ```shell -br --pd ${PDIP}:2379 backup full +br --pd ${PDIP}:2379 backup full \ --storage "local:///tmp/backup" \ --ratelimit 120 \ --concurrency 4 \ @@ -188,11 +188,13 @@ br --pd ${PDIP}:2379 restore table \ ## 注意事项 +- BR 只支持 TiDB 3.1 版本及以上。 +- 如果在没有网络存储的集群上备份,在恢复前需要将所有备份下来的 SST 文件拷贝到各个 TiKV 节点上。 - TiDB 执行 DDL 期间不能执行备份操作。 - 目前只支持在全新的集群上执行恢复操作。 - 如果备份时间可能超过设定的 GC lifetime(默认 10 分钟),则需要将 GC lifetime 调大。 - 例如,将 GC lifetime 调整为 720 小时。 + 例如,将 GC lifetime 调整为 720 小时: {{< copyable "sql" >}} @@ -201,7 +203,7 @@ br --pd ${PDIP}:2379 restore table \ "update mysql.tidb set variable_value='720h' where variable_name='tikv_gc_life_time'"; ``` -- 为了加快数据恢复速度,可以在恢复操作前,使用 pd-ctl 关闭相关的 scheduler。恢复完成后,再重新添加这些 scheduler。 +- 为了加快数据恢复速度,可以在恢复操作前,使用 pd-ctl 关闭与调度相关的 schedulers。恢复完成后,再重新添加这些 schedulers。 关闭 scheduler: From 8cbe1b54ebdb753f21c4d4ca9fbfd923ff02d9f5 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Thu, 21 Nov 2019 14:00:15 +0800 Subject: [PATCH 16/20] remove --connect Signed-off-by: Neil Shen --- dev/how-to/maintain/backup-and-restore/br.md | 37 +++++++++----------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index 7264e0b71fcf..664a5772f775 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -48,12 +48,6 @@ BR 还包含以下三个子命令: ### 常用选项 * `--pd`:用于连接的选项,表示 PD 服务地址,例如 `"${PDIP}:2379"`。 -* `--connect`:用于连接的选项,表示 TiDB 服务地址,例如 `"root:@tcp(${TiDBIP}:4000)/"`。 - - > **注意:** - > - > 该选项只可用在 `restore` 命令中。使用 BR 恢复集群时必须指定该选项,否则 BR 会报错退出。用例:`br restore table --connect "root:@tcp(${TiDBIP}:4000)/"`。 - * `-h`/`--help`:获取所有命令和子命令的使用帮助。例如 `br backup --help`。 * `--ca`:指定 PEM 格式的受信任 CA 的证书文件路径。 * `--cert`:指定 PEM 格式的 SSL 证书文件路径。 @@ -71,7 +65,8 @@ BR 还包含以下三个子命令: {{< copyable "shell-regular" >}} ```shell -br --pd ${PDIP}:2379 backup full \ +br backup full \ + --pd ${PDIP}:2379 \ --storage "local:///tmp/backup" \ --ratelimit 120 \ --concurrency 4 \ @@ -83,12 +78,13 @@ br --pd ${PDIP}:2379 backup full \ 备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。进度条效果如下: ```shell -br --pd ${PDIP}:2379 backup full \ +br backup full \ + --pd ${PDIP}:2379 \ --storage "local:///tmp/backup" \ --ratelimit 120 \ --concurrency 4 \ --log-file backupfull.log -Full Backup <---------↖................................................> 17.12%. +Full Backup <---------/................................................> 17.12%. ``` ### 备份单张表的数据 @@ -100,7 +96,8 @@ Full Backup <---------↖................................................> 17.12 {{< copyable "shell-regular" >}} ```shell -br --pd ${PDIP}:2379 backup table \ +br backup table \ + --pd ${PDIP}:2379 \ --db test \ --table usertable \ --storage "local:///tmp/backup" \ @@ -124,23 +121,23 @@ br --pd ${PDIP}:2379 backup table \ {{< copyable "shell-regular" >}} ```shell -br --pd ${PDIP}:2379 restore full \ +br restore full \ + --pd ${PDIP}:2379 \ --storage "local:///tmp/backup" \ - --connect "root:@tcp(${TiDBIP}:4000)/" \ --concurrency 128 \ --log-file restorefull.log ``` -以上命令中 `--connect` 选项指定了需要恢复的集群地址。`--concurrency` 指定了该恢复任务内部的子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 +`--concurrency` 指定了该恢复任务内部的子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。进度条效果如下: ```shell -br --pd ${PDIP}:2379 restore full \ +br restore full \ + --pd ${PDIP}:2379 \ --storage "local:///tmp/backup" \ - --connect "root:@tcp(${TiDBIP}:4000)/" \ --log-file restorefull.log -Full Restore <---------↖...............................................> 17.12%. +Full Restore <---------/...............................................> 17.12%. ``` ### 恢复某个数据库 @@ -152,10 +149,10 @@ Full Restore <---------↖...............................................> 17.12 {{< copyable "shell-regular" >}} ```shell -br --pd ${PDIP}:2379 restore db \ +br restore db \ + --pd ${PDIP}:2379 \ --db "test" \ --storage "local:///tmp/backup" \ - --connect "root:@tcp(${TiDBIP}:4000)/" \ --log-file restorefull.log ``` @@ -170,11 +167,11 @@ br --pd ${PDIP}:2379 restore db \ {{< copyable "shell-regular" >}} ```shell -br --pd ${PDIP}:2379 restore table \ +br restore table \ + --pd ${PDIP}:2379 \ --db "test" \ --table "usertable" \ --storage "local:///tmp/backup" \ - --connect "root:@tcp(${TiDBIP}:4000)/" \ --log-file restorefull.log ``` From a5cab5096662b6a99ebbab637720b5678d9f9e59 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Mon, 25 Nov 2019 17:14:54 +0800 Subject: [PATCH 17/20] Address comments Signed-off-by: Neil Shen --- dev/how-to/maintain/backup-and-restore/br.md | 14 +++++++++----- .../maintain/backup-and-restore/mydumper-loader.md | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index 664a5772f775..2a2768aa6ea3 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -6,7 +6,7 @@ category: reference # 使用 BR 进行备份与恢复 -Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行数据备份和恢复。相比 Mydumper,BR 更适合大数据量的场景。本文档介绍了 BR 的工作原理、命令行描述以及详细的备份恢复用例。 +Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行数据备份和恢复。相比 Mydumper/Loader,BR 更适合大数据量的场景。本文档介绍了 BR 的工作原理、命令行描述以及详细的备份恢复用例。 ## 工作原理 @@ -42,7 +42,7 @@ BR 由多层命令组成。目前,BR 包含 `backup`、`restore` 和 `version` BR 还包含以下三个子命令: * `full`:可用于备份或恢复全部数据。 -* `db`:可用于备份或恢复集群中的指定数据库。 +* `db`:可用于恢复集群中的指定数据库。 * `table`:可用于备份或恢复集群指定数据库中的单张表。 ### 常用选项 @@ -56,6 +56,8 @@ BR 还包含以下三个子命令: ## 备份集群数据 +使用 `br backup` 命令来备份集群数据。可选择添加 `full` 或 `table` 子命令来备份全部集群数据或单张表的数据。 + ### 备份全部集群数据 要备份全部集群数据,可使用 `br backup full` 命令。该命令的使用帮助可以通过 `br backup full -h` 或 `br backup full --help` 来获取。 @@ -73,7 +75,7 @@ br backup full \ --log-file backupfull.log ``` -以上命令通过 `--ratelimit` 和 `--concurrency` 选项限制了 **每个 TiKV** 执行备份任务的并发数上限和速度上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 +以上命令通过 `--ratelimit` 和 `--concurrency` 选项限制了 **每个 TiKV** 执行备份任务的速度上限和并发数上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。进度条效果如下: @@ -112,6 +114,8 @@ br backup table \ ## 恢复集群数据 +使用 `br restore` 命令来恢复集群数据。可选择添加 `full`、`db` 或 `table` 子命令来恢复全部集群数据、某个数据库或某张数据表。 + ### 恢复全部备份数据 要将全部备份数据恢复到集群中来,可使用 `br restore full` 命令。该命令的使用帮助可以通过 `br restore full -h` 或 `br restore full --help` 来获取。 @@ -179,14 +183,14 @@ br restore table \ ## 最佳实践 -- 推荐在 `-s` 指定的备份路径上挂载一个共享存储,例如 NFS。这样能方便收集和管理备份操作。 +- 推荐在 `-s` 指定的备份路径上挂载一个共享存储,例如 NFS。这样能方便收集和管理备份文件。 - 在使用共享存储时,推荐使用高吞吐的存储硬件,因为存储的吞吐会限制了备份/恢复的速度。 - 推荐在业务低峰时执行备份操作,这样能最大程度地减少对业务的影响。 ## 注意事项 - BR 只支持 TiDB 3.1 版本及以上。 -- 如果在没有网络存储的集群上备份,在恢复前需要将所有备份下来的 SST 文件拷贝到各个 TiKV 节点上。 +- 如果在没有网络存储的集群上备份,在恢复前需要将所有备份下来的 SST 文件拷贝到各个 TiKV 节点上 `--storage` 指定的目录下。 - TiDB 执行 DDL 期间不能执行备份操作。 - 目前只支持在全新的集群上执行恢复操作。 - 如果备份时间可能超过设定的 GC lifetime(默认 10 分钟),则需要将 GC lifetime 调大。 diff --git a/dev/how-to/maintain/backup-and-restore/mydumper-loader.md b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md index 565b2a15ecb8..64c3eba8acb0 100644 --- a/dev/how-to/maintain/backup-and-restore/mydumper-loader.md +++ b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md @@ -5,7 +5,7 @@ category: how-to # 备份与恢复 -本文档将详细介绍如何使用 mydumper/loader 对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/dev/reference/tidb-binlog/overview.md)。 +本文档将详细介绍如何使用 Mydumper/Loader 对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/dev/reference/tidb-binlog/overview.md)。 这里我们假定 TiDB 服务信息如下: From ea2d13d35e8ac1f43c37b89efc5566c4cf2dafa2 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Mon, 25 Nov 2019 18:00:27 +0800 Subject: [PATCH 18/20] Address comments Signed-off-by: Neil Shen --- dev/TOC.md | 2 +- dev/how-to/maintain/backup-and-restore/br.md | 20 +++++++++---------- .../backup-and-restore/mydumper-loader.md | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dev/TOC.md b/dev/TOC.md index 0c903938278f..82ac701aaae2 100644 --- a/dev/TOC.md +++ b/dev/TOC.md @@ -59,7 +59,7 @@ - [从 CSV 迁移](/dev/reference/tools/tidb-lightning/csv.md) + 运维 - [Ansible 常见运维操作](/dev/how-to/maintain/ansible-operations.md) - - [使用 mydumper/loader 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/mydumper-loader.md) + - [使用 Mydumper/Loader 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/mydumper-loader.md) - [使用 BR 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/br.md) - [定位慢查询](/dev/how-to/maintain/identify-slow-queries.md) + 扩容缩容 diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index 2a2768aa6ea3..f667a2e39fdf 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -62,26 +62,26 @@ BR 还包含以下三个子命令: 要备份全部集群数据,可使用 `br backup full` 命令。该命令的使用帮助可以通过 `br backup full -h` 或 `br backup full --help` 来获取。 -用例:将所有集群数据备份到各个 TiKV 节点的 `/tmp/backup` 路径 +用例:将所有集群数据备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下 {{< copyable "shell-regular" >}} ```shell br backup full \ - --pd ${PDIP}:2379 \ + --pd "${PDIP}:2379" \ --storage "local:///tmp/backup" \ --ratelimit 120 \ --concurrency 4 \ --log-file backupfull.log ``` -以上命令通过 `--ratelimit` 和 `--concurrency` 选项限制了 **每个 TiKV** 执行备份任务的速度上限和并发数上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 +以上命令通过 `--ratelimit` 和 `--concurrency` 选项限制了 **每个 TiKV** 执行备份任务的速度上限(单位 MiB/s)和并发数上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。进度条效果如下: ```shell br backup full \ - --pd ${PDIP}:2379 \ + --pd "${PDIP}:2379" \ --storage "local:///tmp/backup" \ --ratelimit 120 \ --concurrency 4 \ @@ -93,13 +93,13 @@ Full Backup <---------/................................................> 17.12%. 要备份集群中指定单张表的数据,可使用 `br backup table` 命令。同样可通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 `table` 的使用帮助。 -用例:将表 `test.usertable` 备份到各个 TiKV 节点的 `/tmp/backup` 路径 +用例:将表 `test.usertable` 备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下。 {{< copyable "shell-regular" >}} ```shell br backup table \ - --pd ${PDIP}:2379 \ + --pd "${PDIP}:2379" \ --db test \ --table usertable \ --storage "local:///tmp/backup" \ @@ -126,7 +126,7 @@ br backup table \ ```shell br restore full \ - --pd ${PDIP}:2379 \ + --pd "${PDIP}:2379" \ --storage "local:///tmp/backup" \ --concurrency 128 \ --log-file restorefull.log @@ -138,7 +138,7 @@ br restore full \ ```shell br restore full \ - --pd ${PDIP}:2379 \ + --pd "${PDIP}:2379" \ --storage "local:///tmp/backup" \ --log-file restorefull.log Full Restore <---------/...............................................> 17.12%. @@ -154,7 +154,7 @@ Full Restore <---------/...............................................> 17.12%. ```shell br restore db \ - --pd ${PDIP}:2379 \ + --pd "${PDIP}:2379" \ --db "test" \ --storage "local:///tmp/backup" \ --log-file restorefull.log @@ -172,7 +172,7 @@ br restore db \ ```shell br restore table \ - --pd ${PDIP}:2379 \ + --pd "${PDIP}:2379" \ --db "test" \ --table "usertable" \ --storage "local:///tmp/backup" \ diff --git a/dev/how-to/maintain/backup-and-restore/mydumper-loader.md b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md index 64c3eba8acb0..07def2cd1ef1 100644 --- a/dev/how-to/maintain/backup-and-restore/mydumper-loader.md +++ b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md @@ -1,5 +1,5 @@ --- -title: 使用 mydumper/loader 进行备份与恢复 +title: 使用 Mydumper/Loader 进行备份与恢复 category: how-to --- From fc66af2ab40cc851edce1475ea393b3e0c1ac334 Mon Sep 17 00:00:00 2001 From: TomShawn <1135243111@qq.com> Date: Mon, 25 Nov 2019 20:03:35 +0800 Subject: [PATCH 19/20] maintain: fix wording, add aliases, update v3.1 --- dev/TOC.md | 5 +- dev/how-to/maintain/backup-and-restore/br.md | 20 +- .../backup-and-restore/mydumper-loader.md | 1 + v3.1/TOC.md | 4 +- v3.1/how-to/maintain/backup-and-restore/br.md | 227 ++++++++++++++++++ .../mydumper-loader.md} | 6 +- 6 files changed, 247 insertions(+), 16 deletions(-) create mode 100644 v3.1/how-to/maintain/backup-and-restore/br.md rename v3.1/how-to/maintain/{backup-and-restore.md => backup-and-restore/mydumper-loader.md} (94%) diff --git a/dev/TOC.md b/dev/TOC.md index 82ac701aaae2..73510742c3ab 100644 --- a/dev/TOC.md +++ b/dev/TOC.md @@ -59,8 +59,9 @@ - [从 CSV 迁移](/dev/reference/tools/tidb-lightning/csv.md) + 运维 - [Ansible 常见运维操作](/dev/how-to/maintain/ansible-operations.md) - - [使用 Mydumper/Loader 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/mydumper-loader.md) - - [使用 BR 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/br.md) + + 备份与恢复 + - [使用 Mydumper/Loader 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/mydumper-loader.md) + - [使用 BR 进行备份与恢复](/dev/how-to/maintain/backup-and-restore/br.md) - [定位慢查询](/dev/how-to/maintain/identify-slow-queries.md) + 扩容缩容 - [使用 Ansible 扩容缩容](/dev/how-to/scale/with-ansible.md) diff --git a/dev/how-to/maintain/backup-and-restore/br.md b/dev/how-to/maintain/backup-and-restore/br.md index f667a2e39fdf..65fddf5e986e 100644 --- a/dev/how-to/maintain/backup-and-restore/br.md +++ b/dev/how-to/maintain/backup-and-restore/br.md @@ -1,7 +1,7 @@ --- title: 使用 BR 进行备份与恢复 summary: 了解如何使用 BR 工具进行集群数据备份和恢复。 -category: reference +category: how-to --- # 使用 BR 进行备份与恢复 @@ -10,7 +10,7 @@ Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行 ## 工作原理 -BR 是分布式备份恢复的工具,它将备份和恢复操作命令下发到各个 TiKV 节点,TiKV 收到命令后执行相应的备份和恢复操作。在一次备份或恢复中,各个 TiKV 节点都会有一个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 +BR 是分布式备份恢复的工具,它将备份和恢复操作命令下发到各个 TiKV 节点。TiKV 收到命令后执行相应的备份和恢复操作。在一次备份或恢复中,各个 TiKV 节点都会有一个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 ![br-arch](/media/br-arch.png) @@ -33,7 +33,7 @@ BR 是分布式备份恢复的工具,它将备份和恢复操作命令下发 ### 命令和子命令 -BR 由多层命令组成。目前,BR 包含 `backup`、`restore` 和 `version` 三个命令。 +BR 由多层命令组成。目前,BR 包含 `backup`、`restore` 和 `version` 三个命令: * `br backup` 用于备份 TiDB 集群 * `br restore` 用于恢复 TiDB 集群 @@ -62,7 +62,7 @@ BR 还包含以下三个子命令: 要备份全部集群数据,可使用 `br backup full` 命令。该命令的使用帮助可以通过 `br backup full -h` 或 `br backup full --help` 来获取。 -用例:将所有集群数据备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下 +用例:将所有集群数据备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下。 {{< copyable "shell-regular" >}} @@ -120,7 +120,7 @@ br backup table \ 要将全部备份数据恢复到集群中来,可使用 `br restore full` 命令。该命令的使用帮助可以通过 `br restore full -h` 或 `br restore full --help` 来获取。 -用例:将 `/tmp/backup` 路径中的全部备份数据恢复到集群中 +用例:将 `/tmp/backup` 路径中的全部备份数据恢复到集群中。 {{< copyable "shell-regular" >}} @@ -148,7 +148,7 @@ Full Restore <---------/...............................................> 17.12%. 要将备份数据中的某个数据库恢复到集群中,可以使用 `br restore db` 命令。该命令的使用帮助可以通过 `br restore db -h` 或 `br restore db --help` 来获取。 -用例:将 `/tmp/backup` 路径中备份数据中的某个数据库恢复到集群中 +用例:将 `/tmp/backup` 路径中备份数据中的某个数据库恢复到集群中。 {{< copyable "shell-regular" >}} @@ -164,9 +164,9 @@ br restore db \ ### 恢复某张数据表 -要将备份数据中的某张数据表恢复到集群中,可以使用 `br restore table` 命令。该命令的使用帮助可以通过同样可以通过 `br restore table -h` 或 `br restore table --help` 来获取。 +要将备份数据中的某张数据表恢复到集群中,可以使用 `br restore table` 命令。该命令的使用帮助可通过 `br restore table -h` 或 `br restore table --help` 来获取。 -用例:将 `/tmp/backup` 路径中备份数据中的某个数据表恢复到集群中 +用例:将 `/tmp/backup` 路径下的备份数据中的某个数据表恢复到集群中。 {{< copyable "shell-regular" >}} @@ -184,12 +184,12 @@ br restore table \ ## 最佳实践 - 推荐在 `-s` 指定的备份路径上挂载一个共享存储,例如 NFS。这样能方便收集和管理备份文件。 -- 在使用共享存储时,推荐使用高吞吐的存储硬件,因为存储的吞吐会限制了备份/恢复的速度。 +- 在使用共享存储时,推荐使用高吞吐的存储硬件,因为存储的吞吐会限制备份或恢复的速度。 - 推荐在业务低峰时执行备份操作,这样能最大程度地减少对业务的影响。 ## 注意事项 -- BR 只支持 TiDB 3.1 版本及以上。 +- BR 只支持 TiDB 3.1 及以上版本。 - 如果在没有网络存储的集群上备份,在恢复前需要将所有备份下来的 SST 文件拷贝到各个 TiKV 节点上 `--storage` 指定的目录下。 - TiDB 执行 DDL 期间不能执行备份操作。 - 目前只支持在全新的集群上执行恢复操作。 diff --git a/dev/how-to/maintain/backup-and-restore/mydumper-loader.md b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md index 07def2cd1ef1..e915ecddb332 100644 --- a/dev/how-to/maintain/backup-and-restore/mydumper-loader.md +++ b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md @@ -1,6 +1,7 @@ --- title: 使用 Mydumper/Loader 进行备份与恢复 category: how-to +aliases: ['/docs-cn/dev/how-to/maintain/backup-and-restore/'] --- # 备份与恢复 diff --git a/v3.1/TOC.md b/v3.1/TOC.md index a5a97ecf54b4..4f57fd7e9b9c 100644 --- a/v3.1/TOC.md +++ b/v3.1/TOC.md @@ -60,7 +60,9 @@ - [从 CSV 迁移](/v3.1/reference/tools/tidb-lightning/csv.md) + 运维 - [Ansible 常见运维操作](/v3.1/how-to/maintain/ansible-operations.md) - + [备份与恢复](/v3.1/how-to/maintain/backup-and-restore.md) + + 备份与恢复 + - [使用 Mydumper/Loader 进行备份与恢复](/v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md) + - [使用 BR 进行备份与恢复](/v3.1/how-to/maintain/backup-and-restore/br.md) - [定位慢查询](/v3.1/how-to/maintain/identify-slow-queries.md) + 扩容缩容 - [使用 Ansible 扩容缩容](/v3.1/how-to/scale/with-ansible.md) diff --git a/v3.1/how-to/maintain/backup-and-restore/br.md b/v3.1/how-to/maintain/backup-and-restore/br.md new file mode 100644 index 000000000000..65fddf5e986e --- /dev/null +++ b/v3.1/how-to/maintain/backup-and-restore/br.md @@ -0,0 +1,227 @@ +--- +title: 使用 BR 进行备份与恢复 +summary: 了解如何使用 BR 工具进行集群数据备份和恢复。 +category: how-to +--- + +# 使用 BR 进行备份与恢复 + +Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行数据备份和恢复。相比 Mydumper/Loader,BR 更适合大数据量的场景。本文档介绍了 BR 的工作原理、命令行描述以及详细的备份恢复用例。 + +## 工作原理 + +BR 是分布式备份恢复的工具,它将备份和恢复操作命令下发到各个 TiKV 节点。TiKV 收到命令后执行相应的备份和恢复操作。在一次备份或恢复中,各个 TiKV 节点都会有一个项目的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 + +![br-arch](/media/br-arch.png) + +## BR 命令行描述 + +`br` 命令行是由命令(包括子命令)、选项和参数组成的。命令即不带 `-` 或者 `--` 的字符。选项即带有 `-` 或者 `--` 的字符。参数即命令或选项字符后紧跟的、传递给命令和选项的字符。 + +以下是一条完整的 `br` 命令行: + +`br backup full --pd "${PDIP}:2379" -s "local:///tmp/backup"` + +命令行各部分的解释如下: + +* `backup`:命令 +* `full`:`backup` 的子命令 +* `-s` 或 `--storage`:备份保存的路径 +* `"local:///tmp/backup"`:`-s` 的参数,保存的路径为本地磁盘的 `/tmp/backup` +* `--pd`:PD 服务地址 +* `"${PDIP}:2379"`:`--pd` 的参数 + +### 命令和子命令 + +BR 由多层命令组成。目前,BR 包含 `backup`、`restore` 和 `version` 三个命令: + +* `br backup` 用于备份 TiDB 集群 +* `br restore` 用于恢复 TiDB 集群 +* `br version` 用于查看 BR 工具版本信息 + +BR 还包含以下三个子命令: + +* `full`:可用于备份或恢复全部数据。 +* `db`:可用于恢复集群中的指定数据库。 +* `table`:可用于备份或恢复集群指定数据库中的单张表。 + +### 常用选项 + +* `--pd`:用于连接的选项,表示 PD 服务地址,例如 `"${PDIP}:2379"`。 +* `-h`/`--help`:获取所有命令和子命令的使用帮助。例如 `br backup --help`。 +* `--ca`:指定 PEM 格式的受信任 CA 的证书文件路径。 +* `--cert`:指定 PEM 格式的 SSL 证书文件路径。 +* `--key`:指定 PEM 格式的 SSL 证书密钥文件路径。 +* `--status-addr`:指定 BR 提供 Prometheus 统计的监听地址。 + +## 备份集群数据 + +使用 `br backup` 命令来备份集群数据。可选择添加 `full` 或 `table` 子命令来备份全部集群数据或单张表的数据。 + +### 备份全部集群数据 + +要备份全部集群数据,可使用 `br backup full` 命令。该命令的使用帮助可以通过 `br backup full -h` 或 `br backup full --help` 来获取。 + +用例:将所有集群数据备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下。 + +{{< copyable "shell-regular" >}} + +```shell +br backup full \ + --pd "${PDIP}:2379" \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backupfull.log +``` + +以上命令通过 `--ratelimit` 和 `--concurrency` 选项限制了 **每个 TiKV** 执行备份任务的速度上限(单位 MiB/s)和并发数上限,同时把 BR 的 log 写到 `backupfull.log` 文件中。 + +备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。进度条效果如下: + +```shell +br backup full \ + --pd "${PDIP}:2379" \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backupfull.log +Full Backup <---------/................................................> 17.12%. +``` + +### 备份单张表的数据 + +要备份集群中指定单张表的数据,可使用 `br backup table` 命令。同样可通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 `table` 的使用帮助。 + +用例:将表 `test.usertable` 备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下。 + +{{< copyable "shell-regular" >}} + +```shell +br backup table \ + --pd "${PDIP}:2379" \ + --db test \ + --table usertable \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --concurrency 4 \ + --log-file backuptable.log +``` + +`table` 子命令有 `--db` 和 `--table` 两个选项,分别用来指定数据库名和表名,其余选项含义一致。 + +备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 + +## 恢复集群数据 + +使用 `br restore` 命令来恢复集群数据。可选择添加 `full`、`db` 或 `table` 子命令来恢复全部集群数据、某个数据库或某张数据表。 + +### 恢复全部备份数据 + +要将全部备份数据恢复到集群中来,可使用 `br restore full` 命令。该命令的使用帮助可以通过 `br restore full -h` 或 `br restore full --help` 来获取。 + +用例:将 `/tmp/backup` 路径中的全部备份数据恢复到集群中。 + +{{< copyable "shell-regular" >}} + +```shell +br restore full \ + --pd "${PDIP}:2379" \ + --storage "local:///tmp/backup" \ + --concurrency 128 \ + --log-file restorefull.log +``` + +`--concurrency` 指定了该恢复任务内部的子任务的并发数,同时把 BR 的 log 写到 `restorefull.log` 文件中。 + +恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。进度条效果如下: + +```shell +br restore full \ + --pd "${PDIP}:2379" \ + --storage "local:///tmp/backup" \ + --log-file restorefull.log +Full Restore <---------/...............................................> 17.12%. +``` + +### 恢复某个数据库 + +要将备份数据中的某个数据库恢复到集群中,可以使用 `br restore db` 命令。该命令的使用帮助可以通过 `br restore db -h` 或 `br restore db --help` 来获取。 + +用例:将 `/tmp/backup` 路径中备份数据中的某个数据库恢复到集群中。 + +{{< copyable "shell-regular" >}} + +```shell +br restore db \ + --pd "${PDIP}:2379" \ + --db "test" \ + --storage "local:///tmp/backup" \ + --log-file restorefull.log +``` + +以上命令中 `--db` 选项指定了需要恢复的数据库名字,其余选项含义与 `restore full` 一致。 + +### 恢复某张数据表 + +要将备份数据中的某张数据表恢复到集群中,可以使用 `br restore table` 命令。该命令的使用帮助可通过 `br restore table -h` 或 `br restore table --help` 来获取。 + +用例:将 `/tmp/backup` 路径下的备份数据中的某个数据表恢复到集群中。 + +{{< copyable "shell-regular" >}} + +```shell +br restore table \ + --pd "${PDIP}:2379" \ + --db "test" \ + --table "usertable" \ + --storage "local:///tmp/backup" \ + --log-file restorefull.log +``` + +以上命令中 `--table` 选项指定了需要恢复的表名,其余选项含义与 `restore db` 一致。 + +## 最佳实践 + +- 推荐在 `-s` 指定的备份路径上挂载一个共享存储,例如 NFS。这样能方便收集和管理备份文件。 +- 在使用共享存储时,推荐使用高吞吐的存储硬件,因为存储的吞吐会限制备份或恢复的速度。 +- 推荐在业务低峰时执行备份操作,这样能最大程度地减少对业务的影响。 + +## 注意事项 + +- BR 只支持 TiDB 3.1 及以上版本。 +- 如果在没有网络存储的集群上备份,在恢复前需要将所有备份下来的 SST 文件拷贝到各个 TiKV 节点上 `--storage` 指定的目录下。 +- TiDB 执行 DDL 期间不能执行备份操作。 +- 目前只支持在全新的集群上执行恢复操作。 +- 如果备份时间可能超过设定的 GC lifetime(默认 10 分钟),则需要将 GC lifetime 调大。 + + 例如,将 GC lifetime 调整为 720 小时: + + {{< copyable "sql" >}} + + ``` + mysql -h${TiDBIP} -P4000 -u${TIDB_USER} ${password_str} -Nse \ + "update mysql.tidb set variable_value='720h' where variable_name='tikv_gc_life_time'"; + ``` + +- 为了加快数据恢复速度,可以在恢复操作前,使用 pd-ctl 关闭与调度相关的 schedulers。恢复完成后,再重新添加这些 schedulers。 + + 关闭 scheduler: + + {{< copyable "shell-regular" >}} + + ```shell + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-hot-region-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-leader-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler remove balance-region-scheduler + ``` + + 添加 scheduler: + + {{< copyable "shell-regular" >}} + + ```shell + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-hot-region-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-leader-scheduler + ./pd-ctl -u ${PDIP}:2379 scheduler add balance-region-scheduler + ``` diff --git a/v3.1/how-to/maintain/backup-and-restore.md b/v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md similarity index 94% rename from v3.1/how-to/maintain/backup-and-restore.md rename to v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md index 1451625534ef..c9b80f538039 100644 --- a/v3.1/how-to/maintain/backup-and-restore.md +++ b/v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md @@ -1,11 +1,11 @@ --- -title: 备份与恢复 +title: 使用 Mydumper/Loader 进行备份与恢复 category: how-to ---- +aliases: ['/docs-cn/v3.1/how-to/maintain/backup-and-restore/'] # 备份与恢复 -本文档将详细介绍如何对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/v3.1/reference/tidb-binlog/overview.md)。 +本文档将详细介绍如何使用 Mydumper/Loader 对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/v3.1/reference/tidb-binlog/overview.md)。 这里我们假定 TiDB 服务信息如下: From a995b63d63b7c5dcf60db95315070dc83abd8408 Mon Sep 17 00:00:00 2001 From: TomShawn <1135243111@qq.com> Date: Mon, 25 Nov 2019 20:06:13 +0800 Subject: [PATCH 20/20] maintain: fix wording --- dev/how-to/maintain/backup-and-restore/mydumper-loader.md | 2 +- v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/how-to/maintain/backup-and-restore/mydumper-loader.md b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md index e915ecddb332..9950c7106bab 100644 --- a/dev/how-to/maintain/backup-and-restore/mydumper-loader.md +++ b/dev/how-to/maintain/backup-and-restore/mydumper-loader.md @@ -4,7 +4,7 @@ category: how-to aliases: ['/docs-cn/dev/how-to/maintain/backup-and-restore/'] --- -# 备份与恢复 +# 使用 Mydumper/Loader 进行备份与恢复 本文档将详细介绍如何使用 Mydumper/Loader 对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/dev/reference/tidb-binlog/overview.md)。 diff --git a/v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md b/v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md index c9b80f538039..234e83bc5f6b 100644 --- a/v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md +++ b/v3.1/how-to/maintain/backup-and-restore/mydumper-loader.md @@ -2,8 +2,9 @@ title: 使用 Mydumper/Loader 进行备份与恢复 category: how-to aliases: ['/docs-cn/v3.1/how-to/maintain/backup-and-restore/'] +--- -# 备份与恢复 +# 使用 Mydumper/Loader 进行备份与恢复 本文档将详细介绍如何使用 Mydumper/Loader 对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/v3.1/reference/tidb-binlog/overview.md)。