Ano, je to možné, ale opravdu to potřebujete?
Přemýšlejte dvakrát, než se rozhodnete, že to opravdu musí být dvě samostatné databáze.
Můžete ponechat obě připojení otevřená a vrátit první příkaz, pokud druhý selže.
Pokud byste skutečně potřebovali připravené transakce, pokračujte ve čtení.
Pokud jde o vaše schéma – na straně databáze bych pro pohodlí použil generátory sekvencí a klauzuli RETURNING.
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,
...
);
Nyní budete potřebovat nějaké externí lepidlo – koordinátor distribuovaných transakcí (?) – aby to fungovalo správně.
Trik je v použití PREPARE TRANSACTION
místo COMMIT
. Poté, co budou obě transakce úspěšné, použijte COMMIT PREPARED
.
Doklad o konceptu PHP je níže.
UPOZORNĚNÍ! v tomto kódu chybí kritické část - to je kontrola chyb. Jakákoli chyba v $db2
by měl být zachycen a ROLLBACK PREPARED
by měl být spuštěn na $db1
Pokud nezachytíte chyby, ponecháte $db1
se zmrazenými transakcemi, což je opravdu, opravdu špatné.
<?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'" );
}
?>
A znovu - přemýšlejte, než to použijete. To, co navrhuje Erwin, by mohlo být rozumnější.
Jo a ještě jedna poznámka... Chcete-li používat tuto funkci PostgreSQL, musíte nastavit max_prepared_transactions
konfigurační proměnná na nenulovou hodnotu.