lock-db 0.2.0

Lock manager and deadlock detection for Rust databases - row/range locks, multiple granularities, and wait-for cycle detection.
Documentation

In this release (v0.2.0):

  • Lock modes — shared (S) and exclusive (X), with a const compatibility matrix at the core of every grant decision
  • Sharded lock table — the resource space is partitioned across independent shards so acquisitions on unrelated resources never contend on the same mutex
  • Acquire / release — non-blocking try_acquire, single and bulk release, re-entrant acquisition, and shared-to-exclusive upgrade of a sole holder

Planned across the rest of the 0.x series (see dev/ROADMAP.md):

  • Hierarchical granularities — database, table, page, and row-level locks with intention modes (IS, IX, SIX)
  • Row and range locks — lock individual keys or key ranges for predicate / phantom protection
  • Wait / grant queues — fair, blocking acquisition with upgrade handling
  • Deadlock detection — a wait-for graph with cycle detection and configurable victim selection

Installation

[dependencies]
lock-db = "0.2"

Quick Start

use lock_db::prelude::*;

// One manager, shared across all worker threads behind an `Arc`.
let lm = LockManager::new();
let row = ResourceId::new(1);
let (writer, reader) = (TxnId::new(1), TxnId::new(2));

// The writer takes the row exclusively.
lm.try_acquire(writer, row, LockMode::Exclusive).unwrap();

// A concurrent reader is refused while the write lock is held.
assert_eq!(lm.try_acquire(reader, row, LockMode::Shared), Err(LockError::Conflict));

// Once the writer commits and releases, the reader gets in.
lm.release(writer, row).unwrap();
lm.try_acquire(reader, row, LockMode::Shared).unwrap();

A transaction drops its whole lock set in one call at commit or abort:

use lock_db::prelude::*;

let lm = LockManager::new();
let txn = TxnId::new(1);
for id in 0..3 {
    lm.try_acquire(txn, ResourceId::new(id), LockMode::Exclusive).unwrap();
}
assert_eq!(lm.release_all(txn), 3);

API Overview

For the complete reference with method tables and examples, see docs/API.md.

Examples

Runnable examples live in examples/. Run any of them with cargo run --example <name>:

Example Shows
quick_start Acquire, conflict, release on a single row.
two_phase_locking Growing-phase acquires, then release_all at commit.
shared_upgrade Read under a shared lock, then upgrade to exclusive.
concurrent Many threads contending on one row, with a mutual-exclusion check.

Where It Fits

lock-db is the concurrency-control layer. It is used by:

  • txn-db — transactions acquire and release locks here to enforce isolation
  • page-db — page-granularity locks coordinate with the paged store
  • index-db — range locks protect B+tree key ranges against phantoms
  • storage engines — any engine needing pessimistic concurrency control

It has no first-party dependencies, so it builds and tests standalone today.

Cross-Platform Support

Linux (x86_64, aarch64), macOS (x86_64, Apple Silicon), and Windows (x86_64) are first-class and verified by the CI matrix.

Contributing

See CONTRIBUTING.md and dev/DIRECTIVES.md. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.