#71705·tidb

copr: lock-fallback retry keeps replica_read=true on the leader, bypassing TiKV In-Memory Engine

Author: sanketkediaCreated Sep 30, 2026Updated Sep 30, 2026
Labelstype/bugcontributioncomponent/tikvseverity/moderate

Bug Report

After a coprocessor request meets a lock, TiDB retries it on the leader but leaves Context.replica_read = true on the retry. The leader receives a request that claims to be a replica read.

On TiKV v8.5 this makes the leader skip the In-Memory Engine (IME). The retry is served from RocksDB even though the region is cached in IME on the leader. When there is a lot of MVCC garbage (e.g. GC paused on a queue-like index with frequent updates), these retries become slow. They can hit tikv_client_read_timeout and set off more retries.

1. Minimal reproduce step (Required)

  1. TiDB v8.5 + TiKV v8.5 with in-memory-engine.enable = true.
  2. SET GLOBAL tidb_replica_read = 'prefer-leader';
  3. Create a table with a secondary index and read it repeatedly so IME auto-loads its region on the leader.
  4. Run writers that keep prewrite locks on that index range while readers scan the same range
  5. In TiDB logs for retried cop tasks (e.g. throwing pseudo region error due to no replica available), the lock-retry attempt shows replica-read-type=leader together with replica-access: {replica_read, peer:<leader peer>...}.
  6. On the leader TiKV, tikv_snapshot_type_count{type="wasted"} tracks tikv_coprocessor_request_error{reason="meet_lock"}, and index coprocessor requests are served by RocksDB instead of index_by_in_memory_engine.

2. What did you expect to see? (Required)

A lock-fallback retry sent to the leader is a normal leader read (replica_read = false) and uses IME, like the first attempt did.

3. What did you see instead (Required)

The retry reaches the leader with replica_read = true, the leader drops the IME snapshot, and the scan goes to RocksDB.

4. What is your TiDB version? (Required)

8.5. But the code path is same even on master