作者: Jasper
问题背景
集群版本: v5.4.3
集群 TiKV 使用空间持续上涨, truncate 及 drop table 操作均无法正常释放空间
问题排查
- 从 grafana 监控观察 tikv store size 是在持续上涨的
- dashboard 发现 unexpected resolve 报错
- 根据报错详细日志查询确认 attempted_commit_ts < min_commit_ts
至此确认事务状态异常导致 resolve lock 阶段不能正常进行,以至于无法进行GC。
问题解决
- 根据 dashboard 查找 443765878275179110 这个 ts 相关的 key,定位到 key 是 74800000000000a4255f698000000000000001013632323138383330ff3030313136303035ff3038310000000000fa0380000000004fbb7a,
- 跟据 key 信息定位到相关表的id 为 42021
- 根据相关的key 查找到对应的 region 信息
Region_id 为 333744437,分别存在于 4,6,8 三个store
- 查询对应的表是否还存在,发现表已经被 truncate,对应的key已经确认被删除,可以进行下一步操作
- 通过 region 信息定位到具体的 store,查询方法如下:
- 对获取到的 key 进行编码
- 对编码编辑到如下命令(此步骤只是准备命令,并不是真实执行)
- 分别登陆第 5 步查到的三个 tikv 实例进行操作
关闭 tikv 进程
以只读方式查询 region 中mvcc的信息
查询结果如下: 其中有一个 lock
执行第 7 步准备的命令,进行进一步确认
执行结果如下,可看到 start_ts 中的信息与 TiDB 日志中输出的问题 Key 的 start_ts 信息一致,确认其即为需要修复的 key
执行修复命令
执行结果如下,可以看到对应的 lock已经消失
修复完成后启动 tikv 进程
- 按照第8步的操作分别修复其余两个 store (操作过程略)
- 查看 监控发现存储空间已经正常释放
- 查看 GC safepoint 并转换成时间,发现 safepoint 已经推进到当天
原理解释:
GC 完整流程大概分为以下三步
- Resolve Locks:该阶段会对所有 Region 扫描 Safepoint 之前的锁,并清理这些锁。
- Delete Ranges:该阶段快速地删除由于 DROP TABLE/DROP INDEX 等操作产生的整区间的废弃数据。
- Do GC:该阶段每个 TiKV 节点将会各自扫描该节点上的数据,并对每一个 key 删除其不再需要的旧版本。
本次故障是由于集群网络不稳定,长期运行中疑似引发了一个概率很低的问题,写入了错误的 lock,这个 lock 导致 GC 的 resolve lock 步骤无法成功执行。根据当前监控可以看到集群中网络延迟较高。 可以看到集群中各个节点互 ping 间断性会达到 1s 以上。
引发问题过程过程概要
- txn1 prewrite key1,key2,key3, key1 meet network error, retry and success. key1, key2,key3 finished
- txn2 meet lock key1(txn1), and find all locks(key1,key2,key3) for txn1 exist, so it commit the txn1
- txn1's first prewrite to lock key1, success.
resolve lock 失败的原因是太晚到的那个 prewrite 请求(step3)因为是用了 async commit 的,它通过那个 tikv 节点上的 max_ts 算出了更大的 min_commit_ts 字段,而原来那个事务(txn1)早就已经用一个更小的 commit ts 提交了,所以 resolve lock 的时候 commit ts 检查出问题而导致无法正常 GC
总结
- Workaround
可以通过关闭全局 async commit 以及 1pc 避免此类问题的发生,关闭此参数可能会导致集群性能少许降低。
推荐保持当前配置,关闭方法如下:
- 相关 issue:https://github.com/tikv/tikv/issues/11187
- 在日常使用过程中,要及时关注集群中 GC safepoint 相关的告警,以及tikv 磁盘使用率 如果发现异常及时介入处理,规避容量风险和集群可用性风险。