HeliosDB MVCC Configuration Guide
HeliosDB MVCC Configuration Guide
Multi-Version Concurrency Control with Serializable Snapshot Isolation
Overview
HeliosDB implements PostgreSQL-compatible MVCC (Multi-Version Concurrency Control) with Serializable Snapshot Isolation (SSI). This guide explains how to correctly configure and use MVCC features, especially for SERIALIZABLE isolation level.
Transaction Isolation Levels
HeliosDB supports four PostgreSQL-compatible isolation levels:
| Isolation Level | Snapshot Created? | Reads Tracked? | Writes Tracked? | Conflict Detection | Overhead |
|---|---|---|---|---|---|
| READ UNCOMMITTED | ❌ No | ❌ No | ❌ No | None | ~0% |
| READ COMMITTED | ❌ No | ❌ No | ❌ No | None | ~0% |
| REPEATABLE READ | Yes | ❌ No | ❌ No | None | <1% |
| SERIALIZABLE | Yes | ⚠ Partial | Yes | Full | 2-5% |
Usage Examples
READ COMMITTED (Default)
-- Default isolation levelBEGIN TRANSACTION;-- orBEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- Non-repeatable reads possibleSELECT balance FROM accounts WHERE id = 1; -- Returns 100-- (Another transaction updates balance to 200)SELECT balance FROM accounts WHERE id = 1; -- May return 200
COMMIT;REPEATABLE READ
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- Repeatable reads guaranteedSELECT balance FROM accounts WHERE id = 1; -- Returns 100-- (Another transaction updates balance to 200)SELECT balance FROM accounts WHERE id = 1; -- Still returns 100 (snapshot)
-- Write conflicts NOT detected (both can commit)UPDATE accounts SET balance = balance + 10 WHERE id = 1;
COMMIT;SERIALIZABLE
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Strict serializabilityUPDATE accounts SET balance = balance + 10 WHERE id = 1;
-- If another transaction modifies id=1 concurrently:COMMIT; -- May fail with "serialization_failure"⚠ Known Limitations
SELECT Queries Don’t Track Reads
Current Limitation: SELECT statements do NOT track reads in the transaction read set, which means read-write conflicts involving SELECT are NOT detected in SERIALIZABLE transactions.
Problem Scenario
-- Transaction 1 (Connection 1)BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;SELECT balance FROM accounts WHERE id = 1; -- Returns 100-- ⚠ READ NOT TRACKED!
-- Transaction 2 (Connection 2)BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;UPDATE accounts SET balance = 200 WHERE id = 1;COMMIT; -- Succeeds
-- Transaction 1 continuesINSERT INTO audit_log (message) VALUES ('balance was 100');COMMIT; -- ❌ BUG: Should fail but succeeds!Expected Behavior: Transaction 1 should abort with serialization_failure because it read data that was later modified.
Actual Behavior: Both transactions commit successfully (INCORRECT).
Workarounds
Option 1: Use SELECT FOR UPDATE (Recommended)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;-- SELECT FOR UPDATE tracks the read as a writeSELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
-- Now conflicts will be detected-- If another transaction updates id=1, this will fail at COMMITOption 2: Use REPEATABLE READ Instead
-- If full serializability isn't required, use REPEATABLE READBEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;SELECT balance FROM accounts WHERE id = 1; -- Snapshot-consistent
-- You get consistent reads but no conflict detectionOption 3: Use UPDATE to Force Tracking
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;-- Dummy UPDATE to force trackingUPDATE accounts SET balance = balance WHERE id = 1;SELECT balance FROM accounts WHERE id = 1;
-- Now the row is tracked in the write setConflict Detection
What Gets Detected
HeliosDB’s SSI implementation detects:
Write-Write Conflicts (UPDATE/DELETE):
-- T1: UPDATE accounts SET balance = balance + 10 WHERE id = 1;-- T2: UPDATE accounts SET balance = balance - 5 WHERE id = 1;-- Result: Second COMMIT fails with serialization_failureRead-Write Conflicts (UPDATE/DELETE):
-- T1: UPDATE accounts SET balance = balance + 10 WHERE id = 1; (reads then writes)-- T2: UPDATE accounts SET balance = balance - 5 WHERE id = 1;-- Result: Second COMMIT fails with serialization_failure❌ Read-Write Conflicts (SELECT + UPDATE): NOT DETECTED
-- T1: SELECT balance FROM accounts WHERE id = 1;-- T2: UPDATE accounts SET balance = 200 WHERE id = 1; COMMIT;-- T1: COMMIT;-- Result: Both succeed (INCORRECT!)Conflict Resolution Strategy
HeliosDB uses First-Committer-Wins:
- The first transaction to COMMIT succeeds
- Later transactions detect conflicts and abort with
serialization_failure - Matches PostgreSQL behavior
Example: Preventing Lost Updates
-- Account starts with balance = 100
-- Transaction 1 (starts at timestamp 100)BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;UPDATE accounts SET balance = balance + 50 WHERE id = 1;-- Read set: {accounts:1}-- Write set: {accounts:1}
-- Transaction 2 (starts at timestamp 101)BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;UPDATE accounts SET balance = balance - 30 WHERE id = 1;-- Read set: {accounts:1}-- Write set: {accounts:1}COMMIT; -- Succeeds (first committer, timestamp 102)
-- Transaction 1 tries to commitCOMMIT;-- ❌ Fails with:-- ERROR: could not serialize access due to concurrent update on key: accounts:1-- DETAIL: Transaction 2 modified accounts:1 (commit_ts: 102) after our snapshot (ts: 100)
-- Final balance = 70 (100 - 30)-- Transaction 1's +50 update is rejectedPerformance Characteristics
Overhead by Isolation Level
| Operation | READ COMMITTED | REPEATABLE READ | SERIALIZABLE |
|---|---|---|---|
| BEGIN | <1μs | +50μs (snapshot) | +50μs |
| SELECT | 0% overhead | 0% overhead | ⚠ 0% |
| INSERT | 0% overhead | 0% overhead | +100ns/row |
| UPDATE | 0% overhead | 0% overhead | +150ns/row |
| DELETE | 0% overhead | 0% overhead | +150ns/row |
| COMMIT | <1μs | +10μs | +1-5ms |
Memory Usage (SERIALIZABLE)
- Per transaction: O(R + W) where R = keys read, W = keys written
- Typical small transaction: 10-100 keys = ~1-10 KB
- Global coordinator: ~10,000 recent commits = ~500 KB - 5 MB
When to Use Each Isolation Level
READ COMMITTED (Default)
- Use when: High throughput required, occasional non-repeatable reads acceptable
- Examples: Analytics queries, reporting, read-heavy workloads
- Performance: Best (0% overhead)
REPEATABLE READ
- Use when: Consistent snapshot needed, but write conflicts acceptable
- Examples: Report generation, data exports, long-running reads
- Performance: Near-zero overhead (<1%)
SERIALIZABLE
- Use when: Strict consistency required, lost updates unacceptable
- Examples: Financial transactions, inventory management, concurrent updates
- Performance: 2-5% overhead, potential for serialization_failure retries
- ⚠ Limitation: SELECT conflicts not detected
Error Handling
Serialization Failures
When a conflict is detected, you’ll receive:
ERROR: could not serialize access due to concurrent update on key: accounts:1SQLSTATE: 40001 (serialization_failure)Monitoring and Debugging
Log Messages
When using SELECT in SERIALIZABLE:
[WARN] ⚠ CRITICAL GAP: SELECT query in SERIALIZABLE transaction does NOT track reads! Read-write conflicts will NOT be detected. This violates serializability. Use SELECT FOR UPDATE as a workaround...Debugging Conflicts
Enable debug logging to see conflict detection.
You’ll see detailed logs:
[DEBUG] Checking for write conflicts (Serializable isolation)[DEBUG] Read set size: 3, Write set size: 2[DEBUG] Checking conflicts for snapshot timestamp 1000[DEBUG] Found 2 transactions committed since our snapshot[WARN] Read-write conflict detected: txn 12345 read key 'accounts:1', but txn 12346 modified it (commit_ts: 1002)Migration from PostgreSQL
If migrating from PostgreSQL, HeliosDB’s MVCC behavior is compatible with one exception:
Compatible Behavior
Same isolation levels Same conflict detection for UPDATE/DELETE Same first-committer-wins semantics Same error codes (40001 for serialization_failure)
Differences
⚠ SELECT in SERIALIZABLE doesn’t track reads
- PostgreSQL: Full SSI including SELECT
- HeliosDB: SELECT not tracked (partial SSI)
- Workaround: Use SELECT FOR UPDATE
References
- PostgreSQL SSI: https://www.postgresql.org/docs/current/transaction-iso.html
- Academic Paper: “Serializable Snapshot Isolation in PostgreSQL” (Ports & Grittner, 2012)
Support
For questions or issues related to MVCC:
- Review log messages for configuration warnings
- Enable DEBUG logging for conflict detection details
- Support: support@heliosdb.com
Version History
- v5.4.0: Initial MVCC SSI implementation
- v5.4.1: Runtime warnings for known limitations added