A database transaction is not just a function containing several writes.
It defines what data the operation can observe and how its changes become visible.
LioranDB separates transactions into read and write transactions.
Read transactions
A read transaction stores a read timestamp.
Every lookup uses that timestamp:
get_at(read_timestamp, table, key)
A scan follows the same idea.
scan_at(read_timestamp, table, range)
The timestamp allows the engine to define which version of a value is visible to that transaction.
Write transactions
A write transaction contains:
Transaction ID
Read timestamp
Write set
The write set is a list of operations:
Put {
table,
key,
value
}
Delete {
table,
key
}
Calling put() does not immediately modify every persistent structure.
Instead, the transaction accumulates operations.
On commit, the complete write set is passed to the engine.
Why collect a write set?
This design enables the engine to:
- Validate conflicts
- Assign a commit timestamp
- Append one logical transaction to the WAL
- Apply several operations atomically
- Collect commit statistics
- Route operations before publishing them
A transaction can therefore fail before partially exposing its updates.
Isolation modes
The engine configuration currently exposes two isolation choices:
SnapshotIsolation
ReadCommitted
Snapshot isolation provides a stable logical view and write-write conflict detection.
Read committed exposes the latest committed state according to the engine's disk-mode semantics.
Isolation is not a checkbox that magically creates correctness.
Every read path, write path, index update, WAL record, and recovery operation must agree on transaction visibility.
The transaction structs in LioranDB look compact because most of the complexity lives underneath them.
That is usually a good sign.
A clean transaction API should hide the machinery, not leak the whole engine through every method signature.
Created by Swaraj Puppalwar under Lioran Group.
Read more:
Top comments (0)