迁移升级 TiDB 集群
本文介绍如何使用 BR 全量备份恢复与 TiCDC 增量数据同步实现 TiDB 集群的迁移升级(又称蓝绿升级)。该方案通过双集群冗余架构与增量同步技术,确保业务流量平滑切换并支持快速回退,为关键业务系统提供高可靠、低风险的升级路径。建议定期升级数据库版本,以持续获得性能优化与新特性,构建安全高效的数据库体系。该方案具体优势如下:
- 风险可控:支持分钟级回退至旧版本集群,确保业务连续性。
- 数据完整:采用多阶段验证机制,确保数据零丢失。
- 业务影响小:仅需一次短暂停机窗口即可完成最终切换。
迁移升级的核心流程如下:
- 风险预检:检查集群状态与方案适用性。
- 准备新集群:基于旧集群的全量备份创建新集群,并升级至目标版本。
- 增量同步:通过 TiCDC 建立正向数据同步通道。
- 切换验证:完成多维度验证后,将业务流量切换至新集群,并建立 TiCDC 回退通道。
- 观察状态:维持回退通道。观察期结束后清理环境。
回退计划:在迁移升级过程中,如果新集群出现故障,可随时将业务流量切换回旧集群。
迁移升级 TiDB 集群的标准化流程和通用操作步骤如下,相关命令以 TiDB Self-Managed 环境为例。
步骤一:评估方案可行性
在开始迁移升级前,需评估相关组件的适用性,并检查集群的健康状态。
检查 TiDB 集群的版本:此迁移升级方案适用于 v6.5.0 及以上版本的 TiDB 集群。
检查 TiCDC 适用性:
- 表结构要求:确保待同步的表包含有效索引,详见 TiCDC 有效索引。
- 功能限制:TiCDC 暂不支持 Sequence、TiFlash DDL 同步等,详见 TiCDC 暂不支持的场景。
- 最佳实践:在切换过程中,应尽量避免在 TiCDC 的上游集群执行 DDL 操作。
检查 BR 适用性:
- 查看 BR 全量备份的兼容性说明,详见 BR 版本兼容性矩阵。
- 检查 BR 备份与恢复功能的已知限制,详见 BR 使用限制。
检查集群健康状态,例如 Region 的健康状态、节点资源利用率等。
步骤二:准备新集群
1. 调整旧集群的 GC lifetime
为确保数据同步链路的稳定性,必须调整系统变量 tidb_gc_life_time
的值,以确保其足以覆盖以下操作及其间隔的总时长:BR 备份、恢复、升级集群版本和创建 TiCDC Changefeed 同步链路。否则,同步任务将进入不可恢复的 failed
状态。此时整个迁移升级的步骤,需要重新开始一个新的全量备份开始执行。
以下示例将 tidb_gc_life_time
调整为 60h
:
-- 查看当前 GC lifetime 设置
SHOW VARIABLES LIKE '%tidb_gc_life_time%';
-- 设置 GC lifetime
SET GLOBAL tidb_gc_life_time=60h;
2. 迁移全量数据到新集群
迁移全量数据到新集群时,需注意以下事项:
版本匹配:执行备份与恢复时,BR 组件的版本需与旧集群的大版本保持一致。
性能影响:BR 备份会占用系统资源,建议在业务低峰期执行备份操作,以减少对业务的影响。
时间预估:在无硬件资源瓶颈(磁盘 IO、网络带宽等)的情况下,可以参考以下时间:
- 备份速度:单个 TiKV 节点数据量为 1 TiB,使用 8 个线程备份大约需 1 小时。
- 恢复速度:单个 TiKV 节点数据量为 1 TiB,平均恢复时间大约为 20 分钟。
配置一致性:确保新旧集群的
new_collations_enabled_on_first_bootstrap
配置项相同,否则 BR 恢复会失败。系统表恢复:执行 BR 恢复时,需使用
--with-sys-table
选项,以恢复部分系统表数据。
迁移全量数据到新集群的具体操作步骤如下:
对旧集群执行 BR 全量备份:
tiup br:${cluster_version} backup full --pd ${pd_host}:${pd_port} -s ${backup_location}记录旧集群的 TSO,用于后续创建 TiCDC Changefeed:
tiup br:${cluster_version} validate decode --field="end-version" \ --storage "s3://xxx?access-key=${access-key}&secret-access-key=${secret-access-key}" | tail -n1部署新集群:
tiup cluster deploy ${new_cluster_name} ${cluster_version} tidb-cluster.yaml将全量备份恢复到新集群:
tiup br:${cluster_version} restore full --pd ${pd_host}:${pd_port} -s ${backup_location} --with-sys-table
3. 升级新集群至目标版本
为节省时间,可执行以下命令进行停机升级。关于更多 TiDB 升级方式,参考使用 TiUP 升级 TiDB。
tiup cluster stop <new_cluster_name> # 暂停集群
tiup cluster upgrade <new_cluster_name> <v_target_version> --offline # 停机升级
tiup cluster start <new_cluster_name> # 启动集群
此外,还需同步旧集群必要的关键配置至新集群,例如系统配置项和系统变量等,以确保业务运行一致性。
步骤三:同步增量数据
1. 建立正向数据同步通道
现在,旧集群为原始版本,新集群已升级至目标版本。接下来,需要建立从旧集群到新集群的正向数据同步通道。
创建 Changefeed 同步任务,其中增量同步起始点
${tso}
为步骤二中记录的备份的准确时间戳 TSO,以避免数据丢失:tiup ctl:${cluster_version} cdc changefeed create --server http://${cdc_host}:${cdc_port} --sink-uri="mysql://${username}:${password}@${tidb_endpoint}:${port}" --config config.toml --start-ts ${tso}检查同步任务状态,确认
tso
或checkpoint
是否在持续推进:tiup ctl:${cluster_version} cdc changefeed list --server http://${cdc_host}:${cdc_port}输出示例如下:
[{ "id": "cdcdb-cdc-task-standby", "summary": { "state": "normal", "tso": 417886179132964865, "checkpoint": "202x-xx-xx xx:xx:xx.xxx", "error": null } }]
在同步增量数据期间,需要持续监控数据同步通道的运行状态,并进行必要调整:
延迟指标:
Changefeed checkpoint lag
应保持在较小范围内,例如 5 分钟内。吞吐健康:
Sink flush rows/s
应持续高于业务写入速率。异常告警:定期检查 TiCDC 节点日志与告警信息。
(可选)测试数据同步:更新一些测试数据,验证 Changefeed 是否能将其同步到新集群。
(可选)调整 TiCDC 的配置项
gc-ttl
(默认值为 24 小时)。当同步任务不可用或因某种原因中断,且无法及时解决时,
gc-ttl
配置可确保 TiCDC 需要消耗的数据保留在 TiKV 中而不被集群 GC 清理。超过此时间后,同步任务将进入failed
状态且无法恢复,而 PD 对应的服务 GC 安全点会继续推进,这种情况下需要重新开始新的备份。增加
gc-ttl
配置的值会累积更多 MVCC 数据,影响与调大tidb_gc_life_time
相同,因此建议设置为合理的足够长的值。
2. 检查数据是否一致
数据同步完成后,需要验证新旧集群数据是否一致。可使用以下方法:
使用 sync-diff-inspector 工具:
./sync_diff_inspector --config=./config.toml使用 sync-diff-inspector 的 snapshot 配置结合 TiCDC 的 Syncpoint 功能,在不停止 Changefeed 同步任务的情况下,对新旧集群数据进行一致性验证。详见 TiDB 主从集群数据校验和快照读。
通过业务数据层面的手工校验方式确认数据一致性,例如对比表的行数是否一致。
3. 检查环境就绪状态
本文使用 BR --with-sys-table
选项恢复部分系统表数据。对于不在恢复范围的内容,需要手动补齐。常见需要检查和补齐的内容包括:
- 权限体系:对比
mysql.user
表。 - 配置:包括各节点的参数配置和系统变量。
- 自增列:在新集群上清除自增 ID 的缓存。
- 统计信息:新集群可使用手动或自动收集方式。
此外,还可对新集群进行扩容,以满足预计的业务负载,并迁移周边运维任务,如告警订阅、定时统计信息收集脚本和数据备份脚本等。
步骤四:切换业务流量及回退
1. 切换前准备
确认同步状态:
- 监控 TiCDC Changefeed 的同步延迟。
- 确保增量同步的吞吐量大于或等于业务写入峰值。
执行多维度验证,例如:
- 确保所有数据和内容验证步骤均已完成,并补充必要的检查项。
- 在新集群上对应用程序进行合理性测试或集成测试。
2. 执行切换
停止应用服务,确保旧集群不再承载业务流量。此外,可以通过以下方式进一步确保集群不会被访问:
锁定旧集群的用户账户:
ALTER USER ACCOUNT LOCK;将旧集群设为只读模式。建议重启旧集群的 TiDB 节点,以清理业务会话连接,防止未进入只读状态的连接:
SET GLOBAL tidb_super_read_only=ON;
确认 TiCDC 追平:
在旧集群进入只读模式后,获取旧集群当前的
up-tso
:SELECT tidb_current_ts();观察 Changefeed
checkpointTs
,确保其大于up-tso
,即 TiCDC 已完成数据同步。
确保新旧集群数据一致:
- 在 TiCDC 追平后,获取新集群的
down-tso
。 - 使用 sync-diff-inspector 工具对比新旧集群在
up-tso
和down-tso
时刻的数据一致性。
- 在 TiCDC 追平后,获取新集群的
暂停 Changefeed 正向同步任务:
tiup ctl:${cluster_version} cdc changefeed pause --server http://${cdc_host}:${cdc_port} -c <changefeedid>重启新集群的 TiDB 节点,以清除自增 ID 的缓存。
检查新集群运行状态,可以通过以下方式确认:
检查 TiDB 版本信息是否与目标版本一致:
tiup cluster display <cluster-name>登录数据库,检查各组件版本是否符合预期:
SELECT * FROM INFORMATION_SCHEMA.CLUSTER_INFO;通过 Grafana 监控服务状态:查看 Overview 面板 > Services Port Status,确保所有服务均为 Up 状态。
建立从新集群到旧集群的逆向数据同步通道。
解锁旧集群的用户账户,并恢复其读写模式:
ALTER USER ACCOUNT UNLOCK; SET GLOBAL tidb_super_read_only=OFF;记录新集群当前的 TSO:
SELECT tidb_current_ts();配置逆向数据同步链路,并确认 Changefeed 任务正常:
- 由于此时业务已停止,可使用当前 TSO。
- 确保
sink-uri
设置为旧集群的地址,以避免回环写入风险。
tiup ctl:${cluster_version} cdc changefeed create --server http://${cdc_host}:${cdc_port} --sink-uri="mysql://${username}:${password}@${tidb_endpoint}:${port}" --config config.toml --start-ts ${tso} tiup ctl:${cluster_version} cdc changefeed list --server http://${cdc_host}:${cdc_port}
切换业务流量到新集群。
检查新集群的负载及运行状态是否正常,可以通过以下 Grafana 面板进行监控:
- TiDB Dashboard > Query Summary:检查 Duration、QPS、Failed Query OPM 监控项是否正常。
- TiDB Dashboard > Server:检查 Connection Count 监控项,查看各节点之间的连接数是否均匀。
此时,业务流量已成功切换至新集群,并建立了 TiCDC 逆向同步通道。
3. 应急回滚
回退方案:
- 定期检查新旧集群的数据一致性,确保逆向同步链路正常运行。
- 观察一段时间,例如一周,如发现问题,可随时切换回旧集群。
- 观察期结束后,关闭 TiCDC 逆向同步链路,并下线旧集群。
应急回滚:流量切回旧集群
适用场景:当业务在短时间内无法解决关键问题时,需要考虑是否实施回退方案。
操作步骤:
- 停止对新集群的业务访问。
- 重新授权业务账户,恢复对旧集群的读写权限。
- 检查逆向同步链路,确认 TiCDC 追平,并确保新旧集群数据一致。
- 切换业务流量回旧集群。
步骤五:结束与清理
经过一段时间的观察,确认业务在新集群上稳定运行后,可下线 TiCDC 逆向同步链路并删除旧集群:
下线 TiCDC 逆向同步链路:
tiup ctl:${cluster_version} cdc changefeed remove --server http://${cdc_host}:${cdc_port} -c <changefeedid>删除旧集群。如果不删除,请确保将
tidb_gc_life_time
恢复为原始值:-- 恢复为变更前的值 SET GLOBAL tidb_gc_life_time=10m;