I have situation in which I have to commit a portion of code as transaction of its own.
I have created a table subtransaction_tbl
:
CREATE TA
There are no autonomous transactions in Postgres before Postgres 11, where SQL procedures were added. Everything that's done in a function is rolled back with the transaction.
Here is a discussion of the feature:
In Postgres 10 or older a workaround could be to (ab-)use dblink:
There is also the related concept of a SAVEPOINT. (Not the same thing!):
plpython has subtransactions (with plpy.subtransaction():
), but that's not the same as autonomous transactions. There is no separate COMMIT
. All it does, is bundle a couple of statements together to make them atomic. Without that, if an exception occurs somewhere in the middle, and you catch that exception, only the code up to this exception would be executed. If you wrap it into a subtransaction, it's all or nothing. This is like using a SAVEPOINT
, not an autonomous transaction. Per documentation:
The subtransaction context manager does not trap errors, it only assures that all database operations executed inside its scope will be atomically committed or rolled back.
Postgres does support nested transactions, but they differ from the conventional SQL, more like transactions with nested partial points.
On the top level you always have your typical BEGIN/COMMIT/ROLLBACK
, and on nested levels you have to use the following commands:
SAVEPOINT name
- creates a new savepoint, with name unique for the transactionRELEASE SAVEPOINT name
- commits the savepoint, though it will only persist if the containing transaction commitsROLLBACK TO SAVEPOINT name
- rolls back the savepointYou would also have to make sure that:
SAVEPOINT
are unique;SAVEPOINT
is propagated upwards to the top level.The last bit is a bit tricky, unless you use a library that can do that for you automatically.
When I wrote pg-promise, I made sure that those two provisions are guaranteed:
level_1
, level_2
, and so on, based on the transaction level;ROLLBACK TO SAVEPOINT name
, plus the top-level ROLLBACK
in case a child transaction fails - all built on the standard promise-chaining logic.See also the limitations of the PostgreSQL nested transactions explained...