Ja, es ist möglich, aber brauchen Sie es wirklich?
Denken Sie zweimal nach, bevor Sie entscheiden, dass dies wirklich zwei getrennte Datenbanken sein müssen.
Sie könnten einfach beide Verbindungen offen halten und den ersten Befehl ROLLBACKEN, wenn der zweite fehlschlägt.
Wenn Sie wirklich vorbereitete Transaktionen benötigen, lesen Sie weiter.
In Bezug auf Ihr Schema - ich würde Sequenzgeneratoren und RETURNING-Klauseln auf Datenbankseite verwenden, nur der Einfachheit halber.
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,
...
);
Jetzt brauchen Sie einen externen Kleber - Distributed Transaction Coordinator (?) - damit das richtig funktioniert.
Der Trick besteht darin, PREPARE TRANSACTION
statt COMMIT
. Nachdem beide Transaktionen erfolgreich waren, verwenden Sie COMMIT PREPARED
.
Der PHP-Proof-of-Concept ist unten.
ACHTUNG! diesem Code fehlt das kritische Teil - das ist Fehlerkontrolle. Jeder Fehler in $db2
sollte abgefangen und ROLLBACK VORBEREITET
werden sollte auf $db1
ausgeführt werden Wenn Sie keine Fehler finden, verlassen Sie $db1
mit eingefrorenen Transaktionen, was wirklich, wirklich schlecht ist.
<?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'" );
}
?>
Und noch einmal - denken Sie nach, bevor Sie es verwenden. Was Erwin vorschlägt, könnte sinnvoller sein.
Oh, und noch eine Anmerkung ... Um diese PostgreSQL-Funktion zu verwenden, müssen Sie max_prepared_transactions
config-Variable auf einen Wert ungleich Null.