Enhance transactional RPC compatibility protection
Author: zyguanCreated Sep 15, 2026Updated Sep 16, 2026
Labelstype/enhancement
Background
Transactional RPC and lock-format evolution can introduce semantics that older clients cannot safely interpret. Shared locks are the recent confirmed example: an old client may misinterpret a LockInfo.shared_lock_infos wrapper as a fake lock, then issue invalid follow-up requests such as CheckTxnStatus(lock_ts=0) or ResolveLock(start_version=0).
This tracking issue covers a fail-closed compatibility defense for transactional RPCs. When a caller cannot safely process a transaction-protocol semantic, tikv must reject that path explicitly rather than expose data that can be misinterpreted or return partial success.
Core design
- Introduce a request-level compatibility declaration for transactional RPC callers, together with a structured incompatible-request error. The concrete encoding and governance model still require design review; candidates include a monotonic transaction protocol version and capability-based alternatives.
- Keep compatibility checks feature-specific. tikv checks the caller declaration at paths that would expose, consume, or incorrectly mutate new transaction semantics; the shared-lock paths are the first implementation scope.
- For an incompatible caller, return a fail-closed response: no shared-lock wrapper, fake lock, partial success, or usable normal result.
- Independently reject invalid transactional parameters, especially fake zero-timestamp transaction requests, before they reach transaction state mutation or assertion paths.
- Use
Context.request_originfor caller auditing and observability. It is not an authentication or authorization mechanism, andUnknowncallers are audited rather than rejected in the first phase. - Ensure both new and legacy callers fail safely: new callers recognize the structured error as terminal, while legacy callers must not treat an incompatible path as successful.
Development Task
- kvproto — Define the compatibility declaration, structured incompatible-request error, required transaction-protocol constants, and any required
RequestOrigin/ Store metadata extensions; regenerate and validate language bindings. - pd — If the selected design requires Store-side compatibility metadata, persist and return it correctly through
PutStore,GetStore, andGetAllStores, including existing Store updates, restart/rollback behavior, and legacy Stores. - tikv — Implement RPC admission, shared-lock-specific fail-closed checks, structured error encoding with legacy-safe behavior, invalid transaction-request validation, caller-audit observability, and end-to-end regression coverage for affected transactional RPCs.
- tiflash (including client-c) — Set
RequestOriginTiFlash, inject and dynamically select the compatibility declaration for direct transactional RPCs, handle incompatible responses safely, and validate that the separate ReadIndex path does not expose shared-lock wrappers. - client-go — Centrally inject the process-level compatibility declaration and request origin for unary and BatchCommands requests; surface incompatible responses as terminal typed errors and cover lock-resolver request paths.
- tidb (including br) — Configure tidb and standalone br caller identity/declaration at process initialization, validate tidb transaction paths and embedded-br behavior, and raise the declared compatibility level only after all relevant paths support the required semantics.
- ticdc — Upgrade/configure client-go integration, set
RequestOriginTiCDC, and validate both logpuller and unsafe resolve-lock paths, including shared-lock expansion and propagated resolver requests.
Source: tikv/tikv