写点什么

TiDB 升级与案例分享(TiDB v4.0.1 → v5.4.1)

  • 2022 年 7 月 29 日
  • 本文字数:5677 字

    阅读完需:约 19 分钟

作者: GreenGuan 原文来源:https://tidb.net/blog/d02ba4a5

为什么要升级?

  1. 低版本 TiDB 周边组件支持不完善,如低版本的 cdc 的支持并不完善,有内存泄露问题等;

  2. 实际工作中触发过 TiDB 的 panic bug;

  3. 在降本增效的大背景下,提升 TiDB 的性能或吞吐量;

  4. 为社区贡献实际业务场景;

如何升级?

TiDB 的升级分为停机升级不停机升级,不停机升级又分平滑升级强制升级(–force),下面简单说明下过程,不对细节过多展开,只介绍核心:

强制升级:

  1. 下载对应版本软件到目标主机上

  2. Upgrading component pd

  3. Upgrading component tikv

  4. 替换软件,不做 leader 选举,直接重启 tikv server

  5. Upgrading component tidb

  6. 在升级 tidb 节点时,在该 tidb 上的所有会话将会断开

  7. Upgrading component prometheus,grafana,alertmanager


优点:


  1. 时间短(笔者做过测试,重启一个 200G 左右的 tikv 节点耗时 1 分钟左右)

  2. 升级结果可控


风险:


  1. 该升级方式强制升级,升级过程中,如果前端应用请求的 leader 正好重启,则会有读写失败的情况发生

  2. 在 4 步失败时,程序需要有重连机制

平滑升级:

  1. 下载对应版本软件到目标主机上

  2. Upgrading component pd

  3. Upgrading component tikv

  4. 在升级 tikv 时会滚动驱逐 leader(超时默认 10 分钟,可调),后重启该节点

  5. Upgrading component tidb

  6. 在升级 tidb 节点时,在该 tidb 上的所有会话将会断开

  7. Upgrading component prometheus,grafana,alertmanager


优点:


  1. 该升级方式为平滑升级(前提是该节点上的 leader 可以在规定时长内驱逐完毕),不会有读写失败的情况发生(tidb 组件重启时除外)


风险:


  1. 升级时间较长,举个例子如果有 3pd,3tidb,100tikv,那么滚动升级的时间至少为 100(节点数量) * 10m(默认超时时间) + pd + tidb + 监控,我们假设  pd + tidb + 监控的升级时长为 10m,那么升级的总时长为 16h

  2. 如果在 3.1 步失败时,群集的版本状态有可能是 一部分新版本,一部分旧版本(笔者曾经遇到过的 pd 节点为 v540 tikv 节点为 v409,好在没出什么问题)

  3. 在 4 步失败时,程序需要有重连机制(同上)

停机升级:

  1. 关闭 TiDB 整个实例 (所有组件)

  2. 软件下载及替换

  3. 启动 TiDB 实例


风险:简单的说就是停服维护


  1. 要通知前端业务,做好接口或程序侧的异常捕获,不要让 error 日志暴增而导致的前端应用崩溃

  2. 在停机维护时一定要做好主机硬件检查,主要有硬盘,内存,主板,电源等,如果能关不能开那就尴尬了,避免黑天鹅事件


我们大致总结下每种升级方式的优缺点如下:



具体可参见官方文档,里面写的很清楚,连接如下:


https://docs.pingcap.com/zh/tidb/v5.4/upgrade-tidb-using-tiup

升级前后关注的核心问题

  • 寻找适合的回退方案

  • SQL 兼容问题

  • 性能回退问题

寻找适合的回退方案

原生的 TiDB 升级没有回退方案,如果需要回退方案,可以有如下方案参考:


方案一:备份 / 恢复

   该方案使用的是TiDB 的 br 备份工具,把备份后的结果备份到本地或s3存储中,使用自动化工具进行恢复,如果您当前的群集对ticdc支持的不完善,那么低版本的 TiDB 可以使用该方法,具体操作可以,全量备份 →  增量备份 →  增量恢复 → 增量恢复。
PS:这种方式比较更适合审计验数的场景
复制代码

方案二:TiDB 从库

   该方案比较推荐,适合ticdc支持比较完善的高版本tidb,不过需要注意在同步过程中tso的推进是否正常。切换时,业务侧可以一步一步切换相关业务,按照 只读 → 弱读 → 写 业务逐步迁移,而且在迁移的过程中可以按照需求调整参数;
复制代码

方案三:业务双写

   业务双写,逐步切换,由业务方自主控制数据的写入。该方案dba就不用过多操心了,完全由业务自己控制,但是需要考虑事务的原子性,既A集群写成功,B集群写失败,那么应由业务侧判断事务到底是否成功;
复制代码

方案四:无回退方案

   如果最长恢复时间可接受,那么回退方案是可以取舍的,设计回退方案的成本较高,产生成本主要是回退实例的主机成本、时间成本(验证回退方案的可行性与稳定性)、以及公司业务方的配合度等诸多因素,其核心就是成本与可用性的取舍。
个人认为在小版本升级时回退方案可以忽略 如540 升级 541 因为改动不多,只做bug fix,但大版本升级确实有必要做回退,因为不可控因素较多。
PS:从5版本后,tidb版本的发布规律为 a.b.c ,a代表架构调整,b代表新功能的加入,c代表注重bug修复,既 调架构.新功能.修bug,自行体会哈
复制代码

SQL 兼容问题

一般笔者常用的有如下三个方案,来规避升级高版本后的 SQL 不兼容问题,我给他起名叫“三板斧”:

方案一:mysql-replay 工具回放

   mysql-replay 是官方提供的一个 SQL 回放的工具,该工具会把 tidb 节点网卡流量用 tcpdump 工具抓下来,然后用工具 mysql-replay 工具进行回放(我看了下 asktug 关于该工具的介绍比较少,后期我可以写下这个工具的使用方法),dba需要观察在回放的目标集群中是否有错误日志即可判别线上流量是否兼容目标集群,适合大面积排查兼容性问题,或者在回放的过程中观察目标集群的 Grafana 面板 Overview → TiDB → Failed Query OPM 看在 tidb 层是否有报错(笔者遇到过有 1062 主键冲突报错,这个可以忽略);
复制代码


mysql-replay 工具 git:https://github.com/innerr/workload-sim.tidb.ticat.git

方案二:阅读 TiDB changelog

   阅读每个版本的 changelog,阅读时有个技巧,我们只需要关注如下两部分内容即可:兼容性更改  → tidb 、bug修复 → tidb 
复制代码

方案三:业务参与

   如果有条件的话可以搭一个新版本的tidb,与业务方一起验证是否有不兼容情况发生,当然这个需要调配业务方的人力资源;
复制代码

性能回退问题

   在升级后有一定概率会遇到性能回退问题,感受最明显的是业务方向DBA反馈SQL变慢了,SQL 语句在 TiDB 中要么基于规则,要么基于代价来选择索引。从这个思路出发,有如下两个方案可规避大部分问题:
复制代码

方案一:手动收集统计信息

   在升级之前,需要对所有的表进行健康度检查,对健康度较低的表手动收集统计信息,让基于代价的索引选择更准确,同时也尽最大可能减小干扰项;
复制代码

方案二:执行计划重绑

   导出已经绑定的执行计划,因为在升级的过程中发现 4 和 5 版本的 mysql.bind\_info 有表结构的差异(新增source ,同时升级后 default\_db 字段为空),最稳的方法就是重新绑定,此时会刷新该表;
复制代码


PS:5 版本有一个叫自动捕获执行计划的功能,既系统自动捕获并绑定最近一次执行计划然后存储在系统表中,这个功能需要根据自己的业务场景斟酌是否打开;

升级 Check Point

前期准备

实施过程

后期跟进

案例分享

案例一、4PD 节点导致的升级失败

案例背景:

   在常规检查后,对某集群进行升级命令,本来以为又是一次平安无事的操作,结果发现在升级 pd 节点时超时,升级退出,升级过程中 TiDB duration 飙高;
复制代码

问题排查:

   由于历史原因本集群有4个pd,我们给pd起个别名,pd\_A(leader)、pd\_B、pd\_C、pd\_D
1\. 要升级 pd\_A ,需要先 transfer pd leader,但是 pd\_A 开始报错 \["invalid timestamp"] ,自己开始循环报错,还没法投票出去选别人;
2\. pd\_B 是公投的新王,准备上位,自己还不确定能不能登基,自己也开始报错 \["redirect but server is not leader"]
3\. pd\_C、pd\_D 我选 pd\_B 当 leader
复制代码


那么问题来了,请问 4 pd 达到多数派同意了么,答案必然是没有,核心问题是有一个节点没投出来票,只有半数同意,所以导致 leader 无法竞选成功,最终升级失败;

解决方案:

   对4pd进行缩容后,再次升级,升级成功
复制代码

案例二、集群 A 升级经验分享

案例背景:

   我们把 TiDB 用作生产环境的 OLTP类业务,而集群 A 属于比较核心的群集,SLA较高,日常平均QPS 5w+,TPS 2w+,单表接近百亿, HA要求保证 99.99%,重要程度可想而知。
升级的原因是 TiDB 版本比较旧 ,对于数据下游如 cdc 功能支持不完善,后期我们对会有容灾和多活的需求,由此需要对当前低版本 TiDB 进行升级,以便扩展对数据下游的支持工作。
复制代码


面临的挑战:

  • 集群规模大:规模大指的有两方面,一来 TB 级别的存储,二来节点数较多 TiDB 20+,TiKV 40+ 

  • 维护窗口短:A 集群白天承接 TP 类业务,晚上有 AP 类业务或业务抽数,在升级时业务方要求 db 不能停;

  • 回退方案落地难:我们选择的回退方案是备份恢复,备份结果不稳定(后续会详细说明),并且第一次恢复用了 86 个小时;

  • 集群 A 涉及的上下游较多,需要解决 SQL 兼容性问题:几乎牵扯到所有的业务线

  • 性能回退:未升级时不确定是否会产生性能回退问题

制定升级方案:

   **升级方式:**原厂工程师了解到我们的业务场景后,推荐使用**强制升级**的方法,因为该实例的SLA较高,升级结果必须可控且窗口时间内必须完成升级,所以采取了短、平、快的强制升级方式,这种方式的弊端是在升级的过程中,业务正好在读写某个 region时 TiKV节点会有 unreachable的错误,如下图;
复制代码



   **窗口时间:**在升级当天业务方会在升级前全量抽取db中的重要业务信息,业务侧做好数据兜底方案。同时对于夜间任务,业务方遵循 迁移/切换/推后/错峰 的原则进行任务编排,避免在升级时读写高峰产生的性能压力,排除干扰项;


**回退方案落地:**
**备份:**我们使用 br 备份到自建 S3 存储中。br 与 S3 的交互分为两个阶段, 一、先遍历所有region存储到 s3,二、连接所有 store 和 S3 中的 sst 文件进行 checksum。如果在 checksum 阶段有 IO 或网络超时,整个br任务就会报失败。而的 S3 是抢占式的,在其他租户使用时,会造成性能问题。最终官方建议我们用 minio 的来替代 S3 进行数据库的备份与恢复,一来原厂默认的测试s3就是minio,二来 minio 对与我们来说是独享的服务,没有资源强占全面提升了全量备份的稳定性。
复制代码


PS:如果遇到 br 备份到自建 S3 失败时,首先需要检查一下 TiDB 的状态,如果正常那么大概率是 s3 不稳定造成的,我总结的报错集锦如下:


ERROR 1: [error="msg:"Io(Os { code: 2, kind: NotFound, message: \"No such file or directory\" })" : [BR:KV:ErrKVUnknown]unknown tikv error"]ERROR 2: [error="msg:"Io(Os { code: 5, kind: Other, message: \"Input/output error\" })" : [BR:KV:ErrKVUnknown]unknown tikv error"]ERROR 3: [error="msg:"Io(Os { code: 11, kind: WouldBlock, message: \"Resource temporarily unavailable\" })" "]ERROR 4: [error="rpc error: code = Unknown desc = Io(Os { code: 107, kind: NotConnected, message: "Transport endpoint is not connected" })"]ERROR 5: [error="NoCredentialProviders: no valid providers in chain. Deprecated.\n\tFor verbose messaging see aws.Config.CredentialsChainVerboseErrors"]ERROR 6: [error="msg:"Io(Custom { kind: Other, error: \"failed to put object Error during dispatch: connection error: Connection reset by peer (os error 104)\" })" "]ERROR 7: [error="error happen in store xxx at xxx:xxx: Io(Custom { kind: Other, error: "failed to put object rusoto error Request ID: None Body: \nERROR 1: InvalidPartOne or more of the specified parts could not be found. The part may not have been uploaded, or the specified entity tag may not match the part's entity tag.....
复制代码


   **恢复:**初次进行恢复时,回滚集群我们采用了 16 个 kv 节点,恢复时间用了 86 个小时,这显然是不能接受的。我们咨询了原厂工程师,建议增加 TiKV 的数量,于是我们尝试同机房搭建集群(TiKV数量少)、跨机房搭建集群(TiKV 数量多)、不同性能主机搭配搭建集群,发现缩短恢复时间需要这么几个条件,同机房、TiKV节点数量不宜过多、主机性能相当的群集恢复效率最高。最终,最快恢复时长 10TB+数据 4h50m,平均恢复时长为7小时左右。
复制代码


PS:v4.0.1 的 br 备份工具比 v4.0.16 的要 40% 左右,我感觉可能是 v4.0.16 在校验部分做了更多的工作,v4.0.1 的 br 恢复与  v4.0.16  处理逻辑也不一样,尤其是对 分区表 ddl 功能,v4.0.1 能成功 v4.0.16 报错 [error=”[ddl:-1]json: cannot unmarshal array into Go value of type string”]


   **SQL兼容性:**使用上文提及的三个方案,不做过多赘述


**性能回退问题:**使用上文提及的两个方案,不做过多赘述
PS:如果使用了上述两个方案还是有性能回退问题,可以尝试推动业务方修改事务提交方式,由乐观改为悲观
复制代码


begin pessimistic;xxx;commit;
复制代码


升级流程:


升级后的收益:

  1. 升级后给我最大的感受是,5 版本比 4 版本更稳定,尽可能去避免抖动产生的性能问题


Query summary 在相同时段 TiDB 内部自动执行的 SQL 语句 999 分位 由之前的 4s 稳定在 125ms 左右提升了 97% ,并解决了性能抖动问题



  1. CPU 方面的性能提升,Raft Store CPU 升级后都在报警阈值以下运行



  1. 写性能能提升: 相比 v4.0.1 TiKV 对 gRPC 模块进行了优化,优化了 Raft 日志复制速度,降低了 Commit Log Duration 和 Store Duration。




业务方反馈:




简单提一下 5 版本带来性能收益,我们从读写两方面来解读


写:异步提交事务 (Async Commit) 与 1pc 提交,异步事务主要解决的是降低事务提交的延迟,1pc 提交指的是只涉及一个 Region 的事务会大幅降低事务提交延迟并提升吞吐;


读:默认开启 Coprocessor cache 功能 降低读取数据的延时;


降低性能抖动:开启 GC in Compaction filter 功能,我理解是在冷数据 compation 为 sst 的同时做 GC,减少单独的 GC worker 做 GC 时的读 MVCC 版本时的压力;

写在最后

   升级数据库是非常核心的项目,因为数据是有状态的并不是 DBA 可以单纯的自行判定是否正常,所以升级需要各业务方联动配合。对于DBA来说 tiup cluster upgrade 一条命令就升上去了,但是升级后业务方是否认可这次升级,是我们需要思考的地方,同时升级的前置、检查、回退、沟通工作一定要做到位,尽量避免黑天鹅事件;简单一句话:不要把升级项目置于被动中
最后十分感谢原厂工程师苏丹和东玫,感谢你们为这个项目协调的资源与升级计划的审核,有原厂的专业指导,大大降低了升级的风险,同时提升了集群升级的成功率,升级后的效果得到了广大 TiDB 使用方的普遍认可。
复制代码


发布于: 3 小时前阅读数: 10
用户头像

TiDB 社区官网:https://tidb.net/ 2021.12.15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
TiDB升级与案例分享(TiDB v4.0.1 → v5.4.1)_实践案例_TiDB 社区干货传送门_InfoQ写作社区