copr: lock-fallback retry keeps replica_read=true on the leader, bypassing TiKV In-Memory Engine
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)
- TiDB v8.5 + TiKV v8.5 with
in-memory-engine.enable = true. SET GLOBAL tidb_replica_read = 'prefer-leader';- Create a table with a secondary index and read it repeatedly so IME auto-loads its region on the leader.
- Run writers that keep prewrite locks on that index range while readers scan the same range
- In TiDB logs for retried cop tasks (e.g.
throwing pseudo region error due to no replica available), the lock-retry attempt showsreplica-read-type=leadertogether withreplica-access: {replica_read, peer:<leader peer>...}. - On the leader TiKV,
tikv_snapshot_type_count{type="wasted"}trackstikv_coprocessor_request_error{reason="meet_lock"}, andindexcoprocessor requests are served by RocksDB instead ofindex_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
Source: pingcap/tidb