Ja, het is mogelijk, maar heb je het echt nodig?
Denk twee keer na voordat je besluit dat dit echt twee aparte databases moeten zijn.
Je kunt gewoon beide verbindingen open houden en de eerste opdracht ROLLBACK als de tweede mislukt.
Als je echt voorbereide transacties nodig hebt, lees dan verder.
Wat betreft je schema - ik zou sequentiegeneratoren en RETURNING-clausule aan de databasekant gebruiken, gewoon voor het gemak.
CREATE TABLE tbl_album (
id serial PRIMARY KEY,
name varchar(128) UNIQUE,
...
);
CREATE TABLE tbl_user_album (
id serial PRIMARY KEY,
album_id bigint NOT NULL,
...
);
Nu heb je wat externe lijm nodig - gedistribueerde transactiecoördinator (?) - om dit goed te laten werken.
De truc is om TRANSACTIE VOORBEREIDEN
in plaats van COMMIT
. Nadat beide transacties zijn geslaagd, gebruikt u COMMIT PREPARED
.
PHP proof-of-concept staat hieronder.
WAARSCHUWING! deze code mist de kritieke onderdeel - dat is foutcontrole. Elke fout in $db2
moet worden gevangen en ROLLBACK VOORBEREID
moet worden uitgevoerd op $db1
Als je geen fouten opmerkt, laat je $db1
. achter met bevroren transacties, wat echt heel erg is.
<?php
$db1 = pg_connect( "dbname=db1" );
$db2 = pg_connect( "dbname=db2" );
$transid = uniqid();
pg_query( $db1, 'BEGIN' );
$result = pg_query( $db1, "INSERT INTO tbl_album(name) VALUES('Absolutely Free') RETURNING id" );
$row = pg_fetch_row($result);
$albumid = $row[0];
pg_query( $db1, "PREPARE TRANSACTION '$transid'" );
if ( pg_query( $db2, "INSERT INTO tbl_user_album(album_id) VALUES($albumid)" ) ) {
pg_query( $db1, "COMMIT PREPARED '$transid'" );
}
else {
pg_query( $db1, "ROLLBACK PREPARED '$transid'" );
}
?>
En nogmaals - denk na voordat je het gaat gebruiken. Wat Erwin voorstelt, is misschien verstandiger.
Oh en nog een opmerking... Om deze PostgreSQL-functie te gebruiken, moet je max_prepared_transactions
config-variabele naar een waarde die niet nul is.