mvcc_cell code review
(Jin Qing's Column, Aug., 2024)
mvcc_cell: Software-transactional memory for Rust
Downloads: 1,475
Transactions are fully isolated and serialized:
- Each transaction sees a fixed snapshot
- Any concurrent commits will be prevented
Example:
rust
let mvcc = Mvcc::new();
// Create a transactional slot
let slot = MvccCell::new(&mvcc, Box::new(0));
// Start concurrent transactions
let mut t1 = mvcc.begin();
let mut t2 = mvcc.begin();
// Uncommitted values are not visible outside the transaction
t1[&slot] = 42;
assert_eq!(t2[&slot], 0);
// First committer wins, regardless of actual modification order
t2[&slot] = 7;
assert!(t2.try_commit().is_ok());
assert!(t1.try_commit().is_err());
// Transactions always read the values that were current when
// begin() was called.
assert_eq!(mvcc.begin()[&slot], 7);
Features
- The minimal implementation of MVCC
- Uses 2 transaction IDs: begin ID and commit ID
- 2 transactions can have the same begin ID
- Commit will increase the global transaction ID
- TxnId only increased on commit
- Any overlap of 2 transactions is regarded as confliction
- MvccCell stores a value with its history and pending writings
- Snapshot isolation: reading and writing are within the snapshot
- Non-blocking: no lock on reading and writing
- Transaction
- The ID of a transaction is private
- Transaction is not Send nor Sync
- Not two-phase commit: try_commit() will commit
- Writing implies reading
- Low Performance: any concurrent read or write to the same slot will fail
- Consistency: Serializable
- Vacuum can cleanup the history