Range Lock NEW IN 7.4 EXPERIMENTAL¶
Version Notice
This feature is only available in FoundationDB 7.4 and later. You are viewing docs for version 7.3.
Range Lock is a feature that blocks write traffic to specific key ranges in FoundationDB. It's primarily used internally by features like Bulk Load to ensure data consistency during bulk operations.
Overview¶
When a range lock is active:
- Reads: Continue to work normally
- Writes: Blocked with
transaction_rejected_range_lockederror - Scope: Must be within user key space (
"" ~ \xff)
Experimental Feature
Range Lock is an experimental feature. The API and behavior may change in future releases.
Lock Types¶
| Type | Description | Status |
|---|---|---|
| Exclusive Read Lock | Blocks writes, allows reads. Only one user can hold this lock. | Implemented |
| Write Lock | Blocks both reads and writes. | Not implemented |
| Non-exclusive Read Lock | Multiple users can read simultaneously. | Not implemented |
Current Implementation
Only the exclusive read lock is currently implemented. Despite its name, it blocks writes (not reads), providing exclusive access for operations like bulk loading.
Use Cases¶
Bulk Load Operations¶
Bulk Load uses range locks to ensure data consistency:
- Lock the target range to prevent user writes
- Load data directly into storage servers
- Release the lock when complete
Custom Data Operations¶
Applications that need exclusive access to a key range for maintenance or migration can use range locks through the Management API.
Management API¶
Range locks are managed through the FoundationDB Management API:
Register Lock Owner¶
Before acquiring locks, register an owner identity:
ACTOR Future<Void> registerRangeLockOwner(
Database cx,
RangeLockOwnerName ownerUniqueID,
std::string description
);
Acquire Lock¶
Take an exclusive read lock on a range:
ACTOR Future<Void> takeExclusiveReadLockOnRange(
Database cx,
KeyRange range,
RangeLockOwnerName ownerUniqueID
);
Release Lock¶
Release the lock when done:
ACTOR Future<Void> releaseExclusiveReadLockOnRange(
Database cx,
KeyRange range,
RangeLockOwnerName ownerUniqueID
);
Query Locks¶
Find existing locks on a range:
ACTOR Future<std::vector<std::pair<KeyRange, RangeLockState>>>
findExclusiveReadLockOnRange(Database cx, KeyRange range);
Error Handling¶
When a transaction writes to a locked range, it receives:
This error is retryable through Transaction.onError(), similar to other conflict errors.
// Transactions automatically retry on range lock errors
loop {
try {
tr.set(key, value);
wait(tr.commit());
break;
} catch (Error& e) {
wait(tr.onError(e)); // Handles range_lock errors
}
}
Internal Design¶
Range lock metadata is stored in system key space:
- Lock data:
\xff/rangeLock/ - Owner registry:
\xff/rangeLockOwner/
Commit Proxy Enforcement¶
- Lock mutations update commit proxy in-memory maps
- When mutations arrive, proxies check lock status
- Locked mutations are rejected in post-resolution phase
- Locking mutations add write conflict ranges for atomicity
Compatibility¶
| Feature | Compatibility |
|---|---|
| Database Lock | Range locks work independently; lock-aware transactions can still update lock metadata |
| Backup/Restore | May cause mutation loss during restore; auto-retry from clean state |
| Version Vector | Not compatible; disable version vector when using range locks |
Limitations¶
- Exclusive read lock is currently the only lock type
- Range must be within user key space
- Not compatible with version vector mode
See Also¶
- Bulk Load & Dump - Primary consumer of range locks
- Audit Storage - Verify data consistency