[Critical bug] 从低于 v6.5 版本的集群升级到不低于 v6.5 版本的集群,TiFlash 元数据可能损坏的问题
大家好,
我们新发现了一个TiDB 的“TiFlash”组件相关 critical bug,详细见下:
产品 | TiDB |
---|---|
组件 | TiFlash |
版本 | 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 7.1.0 7.1.1 7.0.0 7.4.0 6.6.0 7.2.0 7.3.0 7.1.2 7.5.0 6.5.6 7.1.3 6.5.5 7.1.4 7.5.1 7.6.0 6.5.7 6.5.8 8.0.0 6.5.9 |
分类 | Upgrade |
标签 | kbBug |
来源 |
Issue
https://github.com/pingcap/tiflash/issues/9039
当集群中有 TiFlash 副本的情况下,从 v6.5 版本以下升级到不低于 v6.5 后,可能会导致 TiFlash 元数据损坏无法启动的问题。
具体影响的版本:将集群从低于 v6.5 升级到以下 LTS 版本时,TiFlash 可能会遇到此问题:v6.5.0~v6.5.9,v7.1.0~v7.1.5,v7.5.0~v7.5.1。
Root Cause
从低于 v6.5 版本的集群升级到不低于 v6.5 版本,TiFlash 会在内部把存储格式逐步地升级到 PageStorage V3,来提升写性能。
如果表的数据符合一定分布(在升级前 TiFlash 该表的 DeltaTree 存储引擎中 Delta 层没有新写入的数据),那么升级后 “已分配的文件 ID” 会获取到错误的值,导致在后续 TiFlash 运行过程中随着新数据写入,TiFlash 会对元数据进行错误的覆盖。但该问题在 TiFlash 实例重启之前不一定会表现出来。而是在下一次 TiFlash 实例重启的时候,在启动期间因为损坏的元数据导致检查失败,TiFlash 实例启动失败。
Diagnostic Steps
确认集群近期是否有从低于 v6.5 的版本升级操作。
启动失败时,tiflash 的日志报错信息类似:
["Code: 10017, e.displayText() = DB::Exception: try to create external version with invalid state [ver=23783.0] [state={type:VAR_REF, create_ver: 1653.0, is_deleted: true, delete_ver: 21767.0, ori_page_id: 22935.100, being_ref_count: 1, num_entries: 0}]: [type=PUT_EXTERNAL] [page_id=22935.106] [ver=23783.0] …
或者
["Code: 10015, e.displayText() = DB::Exception: Invalid page id, entry not exist [page_id=69.2] [resolve_id=69.2]: keyspace=4294967295 physical_table_id=-1: (while preHandleSnapshot region_id=100, index=3246, term=7) …
Resolution
将集群从低于 v6.5 升级到以下 LTS 版本时,tiflash 可能会遇到错误:v6.5.0~v6.5.9,v7.1.0~v7.1.5,v7.5.0~v7.5.1。
如果需要将集群低于 v6.5.0 升级版本时,建议至少选择 v6.5.10/v7.1.6/v7.5.2/v8.1.0 作为升级后的版本。另外如果用户在升级前没有 TiFlash 实例,在升级到 v6.5 后才部署 TiFlash 实例,则不涉及到 TiFlash 内的数据格式升级,不会遇到此错误。
Workaround
【已经升级后 TiFlash 遇到该问题】
如果遇到了该问题引起的 TiFlash 元数据损坏,则将出现数据损坏的 TiFlash 实例下线,然后重新部署 TiFlash 实例,等待数据重新从 TiKV 同步。
【升级集群版本前如何避免】
如果必须从低于 v6.5 升级到上述受影响的版本,有一种 workaround 可以避免此错误:
- 在升级前将表的 TiFlash 副本设置为 0,并且缩容所有 TiFlash 实例
- 升级集群至目标版本
- 重新部署 TiFlash 实例并添加 TiFlash 副本