Using dblink is no true distributed transaction, because it is possible that the remote transaction succeeds, while the local transaction fails.
To perform a distributed transaction:
Create a normal transaction with BEGIN
or START TRANSACTION
on both databases.
Perform work on both databases.
Once you are done, prepare the transaction on both databases:
PREPARE TRANSACTION 'some_name';
This step will perform everything that could potentially fail during COMMIT
and persist the transaction, but it will not yet commit it.
If that step fails somewhere, use ROLLBACK
or ROLLBACK PREPARED
to abort the transaction on all databases.
Commit the transaction on all databases:
COMMIT PREPARED 'some_name';
This is guaranteed to succeed.
To reliably perform a distributed transaction, you need a transaction manager: that is a piece of software that keeps track of all distributed transactions. This component has to persist its information, so that it can survive a crash. The job of the transaction manager is to commit or rollback any transaction that was left in an incomplete state after a crash.
This is necessary, because prepared transactions will stay around even if you restart the database, and they will hold locks and block VACUUM
progress. Such orphaned prepared transactions can break your database.
Never use distributed transactions without a transaction manager!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…