Full ACID transactions with MVCC snapshot isolation, four isolation levels, up to 4,096 concurrent active transactions, advisory locks, and temporal snapshots.
Every transaction in Absolute DB satisfies all four ACID properties:
| Property | Guarantee | Mechanism |
|---|---|---|
| Atomicity | All changes commit or all roll back — never partial | Undo log + WAL |
| Consistency | Constraints, foreign keys, and CHECK predicates are enforced | Constraint checking at commit |
| Isolation | Concurrent transactions are separated per the configured isolation level | MVCC |
| Durability | Committed data survives crashes and power loss | WAL + CRC-32C + group commit |
Absolute DB uses Multi-Version Concurrency Control (MVCC). When a transaction begins, it takes a consistent snapshot of the database identified by a System Change Number (SCN). All subsequent reads within that transaction see data as of the snapshot SCN — even if other transactions commit changes in the meantime.
Key properties of the MVCC implementation:
BEGIN;
-- All reads see data as of the snapshot taken at BEGIN
SELECT balance FROM accounts WHERE id = 1; -- reads snapshot
-- Writes are visible within this transaction immediately
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- Check: balance changes are visible to this transaction
SELECT balance FROM accounts WHERE id IN (1, 2);
COMMIT; -- durably written to WAL + data pages
Four isolation levels are supported. The default is READ COMMITTED, which is appropriate for most OLTP workloads. Use REPEATABLE READ or SERIALIZABLE for applications that require strict consistency guarantees.
| Level | Dirty Read | Non-Repeatable Read | Phantom Read | Write Skew |
|---|---|---|---|---|
READ COMMITTED | No | Possible | Possible | Possible |
REPEATABLE READ | No | No | No | Possible |
SNAPSHOT | No | No | No | Possible |
SERIALIZABLE | No | No | No | No |
-- Set isolation level for a single transaction
BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM inventory WHERE product_id = 42;
-- ... other work ...
COMMIT;
-- Set isolation level for a serialisable transaction
BEGIN ISOLATION LEVEL SERIALIZABLE;
SELECT sum(balance) FROM accounts;
-- SSI detects any write conflicts that would violate serialisability
COMMIT; -- may raise serialisation failure; retry on error
-- Set default isolation level for the session
SET default_transaction_isolation = 'repeatable read';
Absolute DB supports up to 4,096 concurrent active transactions per server instance. This limit was raised from 256 in the current release to support high-concurrency application servers and connection poolers.
| Property | Current |
|---|---|
| Max concurrent active transactions | 4,096 |
| Max virtual connections (Enterprise) | 16 million |
| Connection pooler support | PgBouncer, Odyssey, pgpool-II |
| Idle transaction timeout | Configurable (idle_in_transaction_session_timeout) |
Savepoints allow partial rollback within a transaction — rolling back to a savepoint undoes all changes made since that savepoint was established, without aborting the entire transaction. Savepoints can be nested to arbitrary depth.
BEGIN;
INSERT INTO orders (customer_id, total) VALUES (42, 199.99);
SAVEPOINT after_insert;
-- Try a risky operation
UPDATE inventory SET qty = qty - 1 WHERE product_id = 7;
-- Check if it went wrong
-- (e.g., qty went negative due to concurrent update)
SELECT qty FROM inventory WHERE product_id = 7;
-- Roll back just the inventory update, keep the order insert
ROLLBACK TO SAVEPOINT after_insert;
-- Continue with a different approach
UPDATE inventory SET qty = qty - 1
WHERE product_id = 7 AND qty > 0;
RELEASE SAVEPOINT after_insert; -- drop the savepoint
COMMIT;
When a transaction runs at the SERIALIZABLE isolation level, Absolute DB uses Serialisable Snapshot Isolation (SSI) to detect and prevent anomalies that ordinary snapshot isolation would allow — specifically write skew and phantom reads in certain concurrent patterns.
SSI works by tracking read and write dependencies between concurrent transactions. If a cycle of dependencies would violate serialisability, the transaction that would create the cycle is aborted with a serialisation failure error (ERROR 40001: could not serialize access). The application should retry the transaction.
-- Both transactions run SERIALIZABLE
-- T1:
BEGIN ISOLATION LEVEL SERIALIZABLE;
SELECT count(*) FROM on_call WHERE dept = 'engineering';
INSERT INTO on_call (name, dept) VALUES ('Alice', 'engineering');
COMMIT; -- may fail with serialisation error
-- T2 (concurrent):
BEGIN ISOLATION LEVEL SERIALIZABLE;
SELECT count(*) FROM on_call WHERE dept = 'engineering';
INSERT INTO on_call (name, dept) VALUES ('Bob', 'engineering');
COMMIT; -- one of T1/T2 will be aborted if a cycle is detected
-- Application retry pattern
DO $$
BEGIN
LOOP
BEGIN
-- ... transactional work ...
EXIT; -- success
EXCEPTION WHEN serialization_failure THEN
-- retry
END;
END LOOP;
END $$;
Absolute DB supports time-travel queries via the AS OF SCN clause. A query with AS OF SCN <value> reads the table as it existed at that System Change Number, returning data that may have since been modified or deleted. VACUUM honours the configured PITR retention window before removing old versions.
-- Get the current SCN
SELECT absdb_current_scn();
-- Read the orders table as it was at SCN 1048576
SELECT * FROM orders AS OF SCN 1048576;
-- Audit: what was Alice's balance 6 hours ago?
SELECT balance
FROM accounts AS OF SCN (
SELECT scn FROM absdb_scn_at(now() - INTERVAL '6 hours')
)
WHERE username = 'alice';
-- Compare current vs historical state
SELECT
current.balance AS current_balance,
historical.balance AS balance_6h_ago,
current.balance - historical.balance AS change
FROM accounts AS current
JOIN accounts AS OF SCN 1048576 AS historical USING (id)
WHERE current.username = 'alice';
Absolute DB supports both SQL:2023 MERGE and PostgreSQL-compatible INSERT ... ON CONFLICT for upsert operations. Both are fully atomic and work correctly under concurrent load.
-- SQL:2023 MERGE statement
MERGE INTO products AS target
USING incoming_products AS source ON target.sku = source.sku
WHEN MATCHED THEN
UPDATE SET price = source.price, updated_at = now()
WHEN NOT MATCHED THEN
INSERT (sku, name, price, created_at)
VALUES (source.sku, source.name, source.price, now());
-- PostgreSQL-compatible UPSERT with RETURNING
INSERT INTO users (email, name, created_at)
VALUES ('alice@example.com', 'Alice', now())
ON CONFLICT (email) DO UPDATE
SET name = EXCLUDED.name,
updated_at = now()
RETURNING id, email, (xmax = 0) AS is_new_row;
-- INSERT ... ON CONFLICT DO NOTHING
INSERT INTO event_log (event_id, type)
VALUES (gen_random_uuid(), 'page_view')
ON CONFLICT (event_id) DO NOTHING;
Advisory locks are application-defined locks that are tracked by the database but carry no automatic semantics. They are widely used by migration tools (Flyway, Liquibase, Alembic, golang-migrate) and workflow systems to serialise access to application-defined resources.
Absolute DB supports up to 65,536 concurrent advisory locks per server. Locks can be shared or exclusive, and can be scoped to a session or a transaction.
| Function | Scope | Behaviour |
|---|---|---|
pg_advisory_lock(key) | Session | Block until exclusive lock acquired |
pg_advisory_try_lock(key) | Session | Return false immediately if lock unavailable |
pg_advisory_unlock(key) | Session | Release exclusive advisory lock |
pg_advisory_lock_shared(key) | Session | Block until shared lock acquired |
pg_advisory_xact_lock(key) | Transaction | Auto-released at end of transaction |
pg_advisory_xact_lock_shared(key) | Transaction | Shared, auto-released at end of transaction |
-- Acquire an exclusive advisory lock (blocks until available)
SELECT pg_advisory_lock(12345);
-- ... critical section ...
SELECT pg_advisory_unlock(12345);
-- Non-blocking try (returns false if unavailable)
SELECT pg_advisory_try_lock(12345) AS acquired;
-- Transaction-scoped advisory lock (auto-released at COMMIT/ROLLBACK)
BEGIN;
SELECT pg_advisory_xact_lock(99999);
-- ... work is serialised while this transaction is open ...
COMMIT; -- lock released automatically
-- Shared advisory lock (multiple readers, exclusive writer)
SELECT pg_advisory_lock_shared(42);
-- ... multiple sessions can hold this simultaneously ...
SELECT pg_advisory_unlock_shared(42);
-5432805064034915249 by default. Absolute DB is fully compatible with these tools out of the box.
| Statement / Function | Description |
|---|---|
BEGIN [ISOLATION LEVEL ...] | Start a transaction with optional isolation level |
COMMIT | Commit the current transaction |
ROLLBACK | Roll back the current transaction |
SAVEPOINT name | Create a named savepoint within a transaction |
ROLLBACK TO SAVEPOINT name | Undo changes back to the named savepoint |
RELEASE SAVEPOINT name | Drop a savepoint (changes are kept) |
SELECT ... AS OF SCN value | Time-travel query at a historical SCN |
absdb_current_scn() | Return the current System Change Number |
absdb_scn_at(timestamp) | Return the SCN closest to a given timestamp |
MERGE INTO ... USING ... ON ... | SQL:2023 MERGE statement |
INSERT ... ON CONFLICT DO UPDATE | UPSERT (PostgreSQL-compatible) |
INSERT ... RETURNING ... | Return column values from inserted/updated rows |
pg_advisory_lock(key) | Acquire exclusive session-scoped advisory lock |
pg_advisory_try_lock(key) | Non-blocking advisory lock attempt |
pg_advisory_unlock(key) | Release session-scoped advisory lock |
pg_advisory_xact_lock(key) | Transaction-scoped advisory lock (auto-released) |
~154 KB binary · zero external dependencies · 2,737 tests passing · SQL:2023 100%