升级前置条件
-
为保证数据正确性,业务表结构定义须满足两个条件:必须要有主键或者唯一索引;若不存在主键,则构成唯一索引的每一个字段都应该被明确定义为
NOT NULL
。 -
应用需要预先在测试环境做好新版TiDB验证,包括SQL兼容性验证、请求延时影响等。
-
确保源集群、目标集群已部署,同时目标集群的业务库表,与源集群不存在冲突。
-
主、备集群需要预留CDC资源,供升级、回退时做增量数据同步使用。
-
业务应避免TiDB升级版本期间,执行 DDL 请求。
升级架构
-
升级
-
部署好目标集群
-
源集群和目标集群通过全量+增量同步搭建好主备异步复制关系。
-
业务停服,待目标集群的数据跟源集群追平,将业务割接到目标集群。
-
-
回滚
-
升级时若业务割接到目标集群,出现异常需要回滚,处理流程跟升级类似,需要搭建目标集群到源集群的增量同步关系。
-
业务停服,待源集群的数据跟目标集群追平,将业务迁回源集群,从而实现回退。
-
升级流程
1.部署CDC集群
CDC用于实现源集群、目标集群搭建主从异步复制关系,实现增量数据同步。
-
进入源集群中控机,编辑CDC扩容配置(如 scale-out-cdc.yml)
cdc_servers:
- host:
port:
ssh_port: -
源集群中控机执行扩容命令
tiup cluster scale-out {集群名} ./scale-cdc.yaml -y --user tidb
2.修改源集群数据GC保留时限
TiDB采用MVCC机制,数据有多版本,通过GC定期清理旧版本的数据实现空间的回收。GC时,数据GC保留时限内的数据,不会被清理,例如数据GC保留时限是24h,则GC时不会清理最近24h的数据。为了保证一致性,目标集群通过全量数据快照 + 增量日志回放同步的方式搭建,必须根据配置足够长的数据GC保留时限,确保变更日志保留时间早于全量数据快照的时间戳,否则会有数据丢失。
进入源集群中控机,连接源集群执行以下SQL修改数据GC保留时限(如修改为24小时:24h)
update mysql.tidb set VARIABLE_VALUE="24h" where VARIABLE_NAME="tikv_gc_life_time"
3.从源集群全量导出
使用 dumpling 工具对源集群备份,将备份数据保存在本地,记录快照的时间戳 TS。
-
进入备集群中控机安装 dumpling 和 lightning 工具(tiup安装最新版本即可)。
tiup install dumpling
tiup install tidb-lightning -
进入 dumpling 安装的机器,执行 dumpling 命令备份源集群数据。(如果中控机磁盘容量不足以容纳源集群备份数据,则需要将dumpling和lightning工具传到备集群其它容量够的机器中)
# 8线程;备份数据目录 /data1/dumpling_data;单个文件最大行数200000指定该参数后 Dumpling 会开启表内并发加速导出,同时减少内存使用;单个文件最大大小为256M
./dumpling -u{TiDB_USER} -h{TiDB_HOST} -P{TiDB_PORT} -p{TiDB_PASSWORD} --filetype sql -t 8 -o {LOCAL_BACKUP_DIR} -r 200000 -F 256MiB -
记录备份时间戳(metadata中的Pos)
cat {LOCAL_BACKUP_DIR}/metadata
# 输出样例
Started dump at: 2023-05-16 08:34:45
SHOW MASTER STATUS:
Log: tidb-binlog
Pos: 441509762969108486
GTID:
Finished dump at: 2023-05-16 08:34:46
4.将全量导入目标集群
需要将全量数据传输到目标集群(整体升级需要考虑这个步骤的耗时影响),并使用 lightning 工具将全量备份数据恢复到目标集群。
-
进入 lightning 安装的机器。编写 lightning 配置文文件 tidb-lightning.toml
[lightning]
# 日志
level = "info"
file = "/data1/tidb-lightning/tidb-lightning.log"
[tikv-importer]
# 选择使用的 local 后端
backend = "local"
# 设置排序的键值对的临时存放地址,目标路径需要是一个空目录
sorted-kv-dir = "/data1/lightning_data"
send-kv-pairs = 65536
range-concurrency = 32
[mydumper]
# 源数据目录。
data-source-dir = "/data1/dumpling_data/"
batch-size = "100GiB"
# 配置通配符规则,默认规则会过滤 mysql、sys、INFORMATION_SCHEMA、PERFORMANCE_SCHEMA、METRICS_SCHEMA、INSPECTION_SCHEMA 系统数据库下的所有表
# 只导入与该通配符规则相匹配的表。详情见相应章节。若不配置该项,导入系统表时会出现“找不到 schema”的异常
filter = ['*.*', '!mysql.*', '!sys.*', '!INFORMATION_SCHEMA.*', '!PERFORMANCE_SCHEMA.*', '!METRICS_SCHEMA.*', '!INSPECTION_SCHEMA.*']
[tidb]
# 目标集群的信息
host = ""
port =
user = ""
password = ""
# 表架构信息在从 TiDB 的“状态端口”获取。
status-port =
# 集群 pd 的地址
pd-addr = "" -
创建设置排序的键值对的临时存放地址,目标路径需要是一个空目录
mkdir /data1/lightning_data
-
在系统后台不挂断地运行 lightning 命令导入快照到备集群
nohup ./tidb-lightning -config ./lightning.toml > nohup.out &
5.开启源>目标集群的增量同步
使用CDC client工具在源集群创建增量同步任务,开启源>目标集群的增量同步。
-
进入源集群 cdc 机器,执行 cdc 同步命令
./cdc cli changefeed create --pd=http://{源集群PD host}:{源集群PD port} --sink-uri="tidb://{备集群连接用户}:{备集群连接密码}@{备集群连接IP}:{备集群连接端口}/" --changefeed-id='simple-replication-task' --sort-engine="unified" --start-ts {dumpling备份时间戳}
-
检查 cdc 同步状态,state 为 normal 则表示正在同步。
./cdc cli changefeed list --pd=http://{源集群PD host}:{源集群PD port}
# 输出样例
[
{
"id": "simple-replication-task",
"summary": {
"state": "normal",
"tso": 441507973180948480,
"checkpoint": "2023-05-16 06:40:58.045",
"error": null
}
}
]
6.恢复源集群数据GC保留时限
进入源集群中控机,连接源集群执行以下SQL修改数据GC保留时限(如修改为24小时:24h)
update mysql.tidb set VARIABLE_VALUE="10m" where VARIABLE_NAME="tikv_gc_life_time";
7.源>目标集群的数据一致性对比
在目标集群数据基本追平源集群后,需要校验源、目标集群的数据一致性。获取 cdc 查询同步任务获取时间戳 TSO,使用工具根据 TSO 校验上下游数据一致性(如果并发大,建议业务低峰时操作)。
在备集群中安装 sync_diff_inspector 工具(下载连接:https://download.pingcap.org/tidb-community-toolkit-v5.4.3-linux-amd64.tar.gz)。
-
在源集群 cdc 机器执行命令获取最新同步的时间戳 tso
./cdc cli changefeed list --pd=http://{源集群PD host}:{源集群PD port}
# 输出样例
[
{
"id": "simple-replication-task",
"summary": {
"state": "normal",
"tso": 441507973180948480,
"checkpoint": "2023-05-16 06:40:58.045",
"error": null
}
}
]
-
编写 sync_diff_inspector 配置文件 config.toml
# Diff Configuration.
######################### Global config #########################
# 检查数据的线程数量,上下游数据库的连接数会略大于该值
check-thread-count = 10
# 如果开启,若表存在不一致,则输出用于修复的 SQL 语句。
export-fix-sql = true
# 只对比表结构而不对比数据
check-struct-only = false
######################### Datasource config #########################
[data-sources]
[data-sources.tidb0]
host = "{源集群连接host}"
port = {源集群端口}
user = "{源集群连接port}"
password = "{源集群连接密码}"
#(可选)使用 TiDB 的 snapshot 功能,如果开启的话会使用历史数据进行对比
# 当 snapshot 设置为 "auto" 时,使用 TiCDC 在上下游的同步时间点,具体参考 <https://github.com/pingcap/tidb-tools/issues/663>
snapshot = "auto"
[data-sources.tidb1]
host = "{目标集群连接host}"
port = {目标集群连接port}
user = "{目标集群连接用户}"
password = "{目标集群连接密码}"
#(可选)使用 TiDB 的 snapshot 功能,如果开启的话会使用历史数据进行对比
# 当 snapshot 设置为 "auto" 时,使用 TiCDC 在上下游的同步时间点,具体参考 <https://github.com/pingcap/tidb-tools/issues/663>
snapshot = "auto"
########################### Routes ###########################
# 如果需要对比大量的不同库名或者表名的表的数据,或者用于校验上游多个分表与下游总表的数据,可以通过 table-rule 来设置映射关系
# 可以只配置 schema 或者 table 的映射关系,也可以都配置
# [routes]
# [routes.rule1] # rule1 是该配置的唯一标识的自定义 id,用于上面 data-sources.route-rules 中
# schema-pattern = "" # 匹配数据源的库名,支持通配符 "*" 和 "?"
# table-pattern = "" # 匹配数据源的表名,支持通配符 "*" 和 "?"
# target-schema = "" # 目标库名
# target-table = "" # 目标表名
# [routes.rule2]
# schema-pattern = "" # 匹配数据源的库名,支持通配符 "*" 和 "?"
# table-pattern = "" # 匹配数据源的表名,支持通配符 "*" 和 "?"
# target-schema = "" # 目标库名
# target-table = "" # 目标表名
######################### Task config #########################
# 配置需要对比的*目标数据库*中的表
[task]
# output-dir 会保存如下信息
# 1 sql: 检查出错误后生成的修复 SQL 文件,并且一个 chunk 对应一个文件
# 2 log: sync-diff.log 保存日志信息
# 3 summary: summary.txt 保存总结
# 4 checkpoint: a dir 保存断点续传信息
output-dir = "./output"
# 上游数据库,内容是 data-sources 声明的唯一标识 id
source-instances = ["tidb0"]
# 下游数据库,内容是 data-sources 声明的唯一标识 id
target-instance = "tidb1"
# 需要比对的下游数据库的表,每个表需要包含数据库名和表名,两者由 `.` 隔开
# 使用 ? 来匹配任意一个字符;使用 * 来匹配任意;详细匹配规则参考 golang regexp pkg: https://github.com/google/re2/wiki/Syntax
target-check-tables = ["{数据库1}", "{数据库2}", "{数据库3}"]
#(可选)对部分表的额外配置,其中 config1 在下面 Table config 配置栏中定义
# target-configs = ["config1"]
######################### Table config #########################
# 对部分表进行特殊的配置,配置的表必须包含在 task.target-check-tables 中
#[table-configs.config1] # config1 是该配置的唯一标识自定义 id,用于上面 task.target-configs 中
# 目标表名称,可以使用正则来匹配多个表,但不允许存在一个表同时被多个特殊配置匹配。
#target-tables = ["schema*.test*", "test2.t2"]
#(可选)指定检查的数据的范围,需要符合 sql 中 where 条件的语法
#range = "age > 10 AND age < 20"
#(可选)指定用于划分 chunk 的列,如果不配置该项,sync-diff-inspector 会选取一些合适的列(主键/唯一键/索引)
#index-fields = ["col1","col2"]
#(可选)忽略某些列的检查,例如 sync-diff-inspector 目前还不支持的一些类型(json,bit,blob 等),
# 或者是浮点类型数据在 TiDB 和 MySQL 中的表现可能存在差异,可以使用 ignore-columns 忽略检查这些列
#ignore-columns = ["",""]
#(可选)指定划分该表的 chunk 的大小,若不指定可以删去或者将其配置为 0。
#chunk-size = 0
#(可选)指定该表的 collation,若不指定可以删去或者将其配置为空字符串。
#collation = "" -
执行校验命令
./sync_diff_inspector --config=./config.toml
8.业务停服
业务侧将所有数据库应用停服,切断所有业务请求连接和流量。
9.待目标集群数据追平,修改数据GC保留时限,记录当前时间戳(回退用)
源集群检查 cdc 同步状态,state 为 normal,且当前同步tso已经追平源集群。
./cdc cli changefeed list --pd=http://{源集群PD host}:{源集群PD port}
# 输出样例
[
{
"id": "simple-replication-task",
"summary": {
"state": "normal",
"tso": 441507973180948480,
"checkpoint": "2023-05-16 06:40:58.045",
"error": null
}
}
]
10.业务割接到目标集群
业务侧修改应用配置,将所有业务请求流量切换到目标集群访问。
11.若无需回退,恢复数据GC保留时限
进入源集群中控机,连接源集群执行以下SQL修改数据GC保留时限(如修改为24小时:24h)
update mysql.tidb set VARIABLE_VALUE="24h" where VARIABLE_NAME="tikv_gc_life_time"
12.停增量同步
进入源集群 cdc 机器,删除掉源>目标集群的增量同步。
使用以下命令删除同步任务:
cdc cli changefeed remove --pd=http://{源集群PD host}:{源集群PD 端口} --changefeed-id simple-replication-task
--changefeed-id=uuid
为需要操作的 changefeed
ID。
删除任务后会保留任务的同步状态信息 24 小时(主要用于记录同步的 checkpoint),24 小时内不能创建同名的任务。如果希望彻底删除任务信息,可以指定 --force
或 -f
参数删除,删除后 changefeed 的所有信息都会被清理,可以立即创建同名的 changefeed。
cdc cli changefeed remove --pd=http://{源集群PD host}:{源集群PD 端口} --changefeed-id simple-replication-task --force
回退流程
如果业务割接到目标集群后出现异常需要回退,需要走回退流程,流程如下图所示:
11.部署CDC集群
-
进入目标集群中控机,编辑CDC扩容配置(如 scale-out-cdc.yml)
cdc_servers:
- host:
port:
ssh_port: -
目标集群中控机执行扩容命令
tiup cluster scale-out {集群名} ./scale-cdc.yaml -y --user tidb
12.开启目标>源集群的增量同步
使用CDC client工具在目标集群创建增量同步任务,开启目标>源集群的增量同步。
-
进入目标集群 cdc 机器,执行 cdc 同步命令
./cdc cli changefeed create --pd=http://{目标集群PD host}:{目标集群PD port} --sink-uri="tidb://{源集群连接用户}:{源集群连接密码}@{源集群连接IP}:{源集群连接端口}/" --changefeed-id='simple-replication-task' --sort-engine="unified" --start-ts {dumpling备份时间戳}
-
检查 cdc 同步状态,state 为 normal 则表示正在同步。
./cdc cli changefeed list --pd=http://{目标集群PD host}:{目标集群PD port}
# 输出样例
[
{
"id": "simple-replication-task",
"summary": {
"state": "normal",
"tso": 441507973180948480,
"checkpoint": "2023-05-16 06:40:58.045",
"error": null
}
}
]
13.目标>源集群的数据一致性对比
跟升级流程的步骤7类似。
14.业务停服
业务侧将所有数据库应用停服,切断所有业务请求连接和流量。
15.待源数据追平
目标集群检查 cdc 同步状态,state 为 normal,且当前同步tso已经追平源集群。
./cdc cli changefeed list --pd=http://{源集群PD host}:{源集群PD port}
# 输出样例
[
{
"id": "simple-replication-task",
"summary": {
"state": "normal",
"tso": 441507973180948480,
"checkpoint": "2023-05-16 06:40:58.045",
"error": null
}
}
]
16.回退割接到目标集群
业务侧回退应用配置,将所有业务请求流量切换到源集群访问。
17.恢复数据GC保留时限
进入目标集群中控机,连接目标集群执行以下SQL修改数据GC保留时限(如修改为24小时:24h)
update mysql.tidb set VARIABLE_VALUE="24h" where VARIABLE_NAME="tikv_gc_life_time"
注意事项
-
整个升级或回退过程注意操作步骤对生产集群的影响,避免对生产环境的资源占用、对业务吞吐量、请求时延等造成影响,如:
-
控制全量导出的并发,建议8个线程以下。
-
传输全量备份数据时注意控制带宽使用。
-
数据库一致性对比的并发,建议10个线程以下。
-
-
升级或回退的业务停服时间,取决于数据增量同步时的追平速度。如果业务写入量不大,停服时间会相对比较短。