Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TXN 803: In-Memory Pessimistic Locks

TXN 607 introduced pessimistic transactions. Before changing a key, a transaction can acquire a pessimistic lock so that another writer cannot reserve the same key at the same time.

Suppose transaction T1 plans to update account/42:

T1 acquires a pessimistic lock on account/42
                         |
                         v
T2 tries to lock account/42 -> conflict

The lock is a reservation for a future write. An ordinary snapshot read can still read the previously committed value.

The normal path stores the reservation in the lock CF. Acquiring it therefore requires a Raftstore write:

AcquirePessimisticLock
          |
          v
Raft replication and apply
          |
          v
lock CF

This makes the lock durable and available on every replica, but it also puts a Raft and RocksDB write on the critical path of lock acquisition.

An in-memory pessimistic lock removes that write for eligible requests. TiKV records the reservation only in the current Region leader's memory and returns the result to TiDB.

AcquirePessimisticLock
          |
          v
leader's in-memory lock table
          |
          v
return success

This table is different from the concurrency manager's in-memory locks introduced in TXN 708. The concurrency manager covers transaction state while a RocksDB write is in flight. An in-memory pessimistic lock can remain the only copy of a successfully acquired reservation until a later transaction command replaces or removes it.

Acquiring a Lock

The transaction scheduler first performs the same MVCC checks as the persistent path. When it looks for a lock on a key, it checks the Region leader's in-memory table before reading the lock CF:

look up the key's lock
          |
          v
check the in-memory table
          |
          +-- found --> use that lock
          |
          v
check the lock CF

This gives transaction commands one logical lock view even though some locks are in memory and others are in RocksDB.

If the lock can be acquired, TiKV tries to insert it into the in-memory table. The table accepts locks only while the local peer is the leader and the request matches its current Raft term and Region version.

These checks prevent a request based on stale Region or leadership information from trusting the wrong table. A stale term or Region version causes the request to retry with current routing information. If the table is temporarily non-writable or its memory limit has been reached, lock acquisition falls back to the persistent Raftstore path.

In-memory locking is enabled only together with pipelined pessimistic locking. Pipelining can return a persistent lock request after its Raft proposal instead of waiting for apply. In-memory locking goes one step further for an eligible request: it skips the proposal entirely.

Replacing the In-Memory Lock

The reservation does not remain in memory for the rest of the transaction. A later command normally changes its state through Raftstore.

For example, prewrite replaces the pessimistic reservation with a prewrite lock in the lock CF. A pessimistic rollback removes the reservation instead.

in-memory pessimistic lock
            |
            | prewrite or rollback
            v
write the new lock-CF state through Raft
            |
            v
apply the Raft command
            |
            v
remove the in-memory entry

Before sending the Raftstore write, TiKV marks the matching in-memory entry as pending removal, but keeps the entry visible to readers. TiKV removes it only after the command applies successfully. If the write fails, the in-memory lock remains.

This prevents another command from observing the lock as absent while its replacement or deletion has not succeeded yet.

Losing the Leader

The table belongs to one leader term. If that peer unexpectedly loses leadership, it clears the table. The new leader starts with an empty table for its new term.

The acquire request may already have returned success, but that reply is valid only for the leader term that produced it. A later request with the old term is rejected as stale. When the transaction retries its prewrite on the new leader, the old reservation is gone, so the prewrite fails and the transaction must acquire the lock again.

In-memory pessimistic locking is therefore an optimization, not durable correctness state. It avoids replicating the initial reservation through Raft; prewrite still validates that reservation before the transaction can proceed.

A planned leader transfer can do better. TiKV has time to move the reservations into durable storage before changing leaders.

Leader Transfer

RAFT 601 described the normal leader-transfer handshake: the target follower catches up and sends an acknowledgement to the current leader. With in-memory locks, TiKV pauses after that first acknowledgement instead of starting the normal Raft handoff immediately.

The current leader freezes its table, so new acquisitions use the persistent path and the set of live reservations stops changing. It then proposes those locks into the lock CF, followed by a special TransferLeader admin command in the same Raft log:

target's first acknowledgement
              |
              v
freeze the in-memory lock table
              |
              v
propose live locks into lock CF
              |
              v
target applies TransferLeader and acknowledges again
              |
              v
begin normal Raft leader transfer

The TransferLeader command is an apply fence, not the handoff itself. Raft applies entries in order, so the target cannot reach the fence until it has applied the lock writes. Its second acknowledgement gives the old leader that evidence, and only then does it begin the normal Raft leader transfer.


Pessimistic locks reduce write conflicts by reserving keys before a transaction changes them. In-memory locks make that reservation cheaper and faster, but leader transfer needs extra steps to preserve the live reservations.