# [KB]-GC-不推进

## Key Words

gc, TiKV, diskspace, gc resolve locks failed

## Description

TiKV 磁盘空间告警，排查发现 GC 未推进。滚动重启 TiKV 后发现无效果，查看 TiDB 日志发现，存在 gc resolve locks failed 的报错：

```golang
["[gc worker] start resolve locks"][uuid=5f90f0eff9c00b9][safePoint=436551949795196928][concurrency=22]
["[gc worker] resolve locks failed"][uuid=5f90f0eff9c00b9][safePoint=436551949795196928][error="context canceled"]
["[gc worker] resolve locks return an error"][uuid=5f90f0eff9c00b9][safePoint=436551949795196928][error="context canceled"]
["[gc worker] runGCJob"][error="context canceled"]
```

## Root Cause

部分 TiKV 版本存在 [bug-26359](https://github.com/pingcap/tidb/issues/26359): 启用 async commit 时可能会出现同一个事务的同一个 index key 被 2 个 commit_ts 提交 2 次,  导致事务正确性约束被 break。这里 resolve lock 持续失败的 key 从日志观察到是一个 index key, 且日志中存在较多 deadlock 报错以及 async commit fallback. 可能存在如下时序关系.

1. txn1 使用 async commit protocol 提交, 其中包含这个 index_key. 
2. txn1 写入的 key 被其他并发事务如 txn2 resolve, 通过 resolve async commit protocol 提交了部分 key, 包括 index_key.
3. txn1 prewrite 操作没有收到 index_key 的 response, 实际上 index_key 在 step 1 中已经被 prewrite 成功. txn1 重试 prewrite index_key, 注意重试 prewrite index_key 的时候不会进行 conflict check, 所以重新 prewrite 了这个 index_key
4. txn1 由于某种原因(如 txn coordinator 角色的 tidb-server 挂掉或者网络隔离), 重试 prewrite 之后没有继续推进 commit 流程
5. index_key 上存在残留的 retry prewrite lock
6. GC 尝试 resolve index_key 上的  lock, 发现 async commit 其他 key 已经提交, 尝试用读到的 commit_ts 提交, 被 index_key 上 retry 写入的  lock 拒绝(commit_ts < min_commit_ts)
7. GC resolve lock 反复 6-7 持续失败, GC 无法推进

## Diagnostic Steps

N/A

## Resolution

升级到未受影响版本

## Workaround

(建议联系 PingCAP Support)

满足以下条件： 1. 只有一个这样的异常 lock 2. 异常 lock 所在 table 已经被 truncate 也就是说，可以放心的将该 lock 清理。

清理过程： 1. 通过 pd-ctl 查出 lock 所在的 region 信息 2. 在 region 所在的 tikv 上，从 leader 开始，分别停机，使用 tikv-ctl 修复所在 region的 MVCC 信息，启动。

## Affected Versions

v5.0.0~v5.0.6

v5.1.0~v5.1.3

v5.2.0~v5.2.3
