Transactions
PizzaSQL supports BEGIN, COMMIT, ROLLBACK, SAVEPOINT, RELEASE, and ROLLBACK TO SAVEPOINT. The implementation is simple and worth understanding precisely, because its guarantees are weaker than PostgreSQL’s.
The model: undo log + global lock
Section titled “The model: undo log + global lock”A transaction is not multi-version concurrency control (MVCC). It is two things:
- A database-wide exclusive lock taken at
BEGINand held untilCOMMITorROLLBACK. While a transaction is open, all other statements on that database (including reads) block. - An in-memory undo log. Each
INSERT,UPDATE, orDELETEinside the transaction appends an entry recording the operation, the table, the primary key, and (forUPDATE/DELETE) the full previous row.
COMMIT simply discards the undo log and releases the lock — writes have already been applied to storage as the statements ran. ROLLBACK replays the undo log in reverse, restoring previous row state, then releases the lock.
Transaction control
Section titled “Transaction control”BEGIN; -- or BEGIN TRANSACTIONUPDATE accounts SET balance = balance - 100 WHERE name = 'alice';UPDATE accounts SET balance = balance + 100 WHERE name = 'bob';COMMIT;BEGIN;INSERT INTO log VALUES (1);SAVEPOINT sp1;INSERT INTO log VALUES (2);ROLLBACK TO sp1; -- undoes the second insertRELEASE sp1;COMMIT; -- keeps the first insertBEGINinside an open transaction is an error.COMMIT/ROLLBACKwith no open transaction is an error.SAVEPOINToutside a transaction implicitly opens one.ROLLBACK TO nameundoes operations back to the savepoint and removes savepoints created after it.RELEASE nameremoves a savepoint; releasing the outer-most savepoint has no effect on the transaction.
Guarantees and limitations
Section titled “Guarantees and limitations”- Rollback is session-level. For ordinary tables with a declared primary key,
ROLLBACKrestores row changes while the engine remains running. The undo log is in memory, so a process failure during an open transaction is not crash-atomic; writes already sent to storage can survive without the in-memory log that would undo them. - Isolation is enforced by the exclusive lock — no other connection sees intermediate state, because they cannot run while the transaction is open. This is stronger than
READ COMMITTED(readers block entirely) but means transactions are effectively serialized. - DDL is not transactional.
CREATE TABLE,DROP TABLE,ALTER TABLE,CREATE INDEX, andDROP INDEXare not recorded in the undo log. Rolling back a transaction does not undo DDL executed inside it. - Durability of individual writes depends on the underlying key-value store’s log, not on the transaction layer. This does not make a multi-statement transaction atomic across an engine crash.
Failed transactions over the wire
Section titled “Failed transactions over the wire”On the PostgreSQL protocol, the connection tracks transaction state. If a statement inside a transaction block errors:
- The connection enters a “failed transaction” state and rejects further commands with SQLSTATE
25P02until the client sendsROLLBACK(orROLLBACK TO SAVEPOINT). - This mirrors PostgreSQL’s aborted-transaction behaviour.
Managed service restrictions
Section titled “Managed service restrictions”- The managed HTTP query and execute endpoints reject transaction statements (
BEGIN,COMMIT,ROLLBACK,SAVEPOINT,RELEASE) with501 Not Implemented, and the/executeendpoint’stransaction: trueflag is rejected too. Use the PostgreSQL wire protocol if you need transactions on the managed service. - The managed PostgreSQL proxy forwards transaction statements to the engine, so transactions work normally over
psql/drivers. - The engine’s own raw HTTP API and CLI do support transaction statements, but those surfaces are internal to the platform.
Practical guidance
Section titled “Practical guidance”- Keep transactions short: they hold a database-wide lock and serialize all traffic on the database.
- Do not rely on rolling back DDL — migrate schema outside of transactions, or test-and-recover manually.
- Prefer the PostgreSQL connection path for anything that needs multi-statement atomicity on the managed service.