Skip to content

Transaction Engine

ParticleDB’s transaction behavior is controlled by two server-start choices:

  • --wal-sync-mode decides durability cost (sync, groupsync, nosync)
  • --txn-mode decides concurrency behavior (fast, occ, zero-copy-occ, table-2pl)

The codebase no longer has a single always-on “serializable snapshot isolation” path. Instead, the engine exposes several operational modes so you can choose between maximum throughput and stronger safety.

The write-ahead log persists mutations before they become durable.

ModeBehaviorTypical use
syncfsync on each commitStronger durability, lower throughput
groupsyncBatch fsync via group commitGeneral production default
nosyncSkip explicit fsyncBenchmarks, reloadable data, ephemeral environments
Terminal window
particledb start --wal-sync-mode sync
particledb start --wal-sync-mode groupsync
particledb start --wal-sync-mode nosync

If --txn-mode is omitted, ParticleDB picks occ by default. When --wal-sync-mode sync is set, the default switches to table-2pl for the strictest semantics.

Transaction mode is selected at server start, not with PostgreSQL SERIALIZABLE session syntax.

Terminal window
particledb start --txn-mode fast
particledb start --txn-mode occ
particledb start --txn-mode zero-copy-occ
particledb start --txn-mode table-2pl
ModeBehaviorNotes
fastMinimal coordination, highest OLTP throughputBulk loads, single-writer benchmarks
occBuffered writes plus commit-time validationGeneral OLTP — safe under concurrency (default)
zero-copy-occPartition-pinned OCC; single-partition txns skip cross-partition coordinationHigh-throughput OLTP on partition-affine workloads (TPC-C, key-value)
table-2plExclusive table locksStrictest serialization, lowest concurrency

row-2pl and zcocc are accepted as aliases for occ and zero-copy-occ respectively.

Within an open transaction, mutations are buffered before commit:

  • INSERT, UPDATE, and DELETE are collected in a transaction buffer
  • reads merge the base snapshot with the transaction overlay
  • COMMIT replays buffered operations
  • ROLLBACK discards them

That overlay is what allows statements later in the same transaction to see rows inserted or updated earlier in the same transaction.

The core lifecycle is standard:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

Two-phase commit is also implemented:

BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
PREPARE TRANSACTION 'transfer_tx_001';
COMMIT PREPARED 'transfer_tx_001';
-- or
ROLLBACK PREPARED 'transfer_tx_001';

ParticleDB parses and executes the common PostgreSQL row-locking forms:

  • FOR UPDATE
  • FOR SHARE
  • NOWAIT
  • SKIP LOCKED

Example:

BEGIN;
SELECT *
FROM jobs
WHERE status = 'pending'
ORDER BY created_at
LIMIT 1
FOR UPDATE SKIP LOCKED;
COMMIT;

The finer PostgreSQL lock modes FOR NO KEY UPDATE and FOR KEY SHARE are not part of the current implementation.

ParticleDB does not currently honor PostgreSQL SERIALIZABLE requests over PG wire. The server explicitly rejects that setting and tells clients to use read committed.

In practice:

  • choose the engine behavior with --txn-mode
  • use normal BEGIN / COMMIT / ROLLBACK in clients
  • do not rely on SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
  • do not rely on savepoints yet
  • Use groupsync + occ or groupsync + table-2pl when you want a safer baseline.
  • Use nosync + fast only when you can tolerate data loss on crash.
  • Use --oltp-partitions for warehouse-affine OLTP workloads such as TPC-C.
  • Keep transactions short so buffered writes and lock hold times stay small.