Tak, to możliwe, ale czy naprawdę tego potrzebujesz?
Zastanów się dwa razy, zanim zdecydujesz, że to naprawdę muszą być dwie oddzielne bazy danych.
Możesz po prostu pozostawić oba połączenia otwarte i wycofać pierwsze polecenie, jeśli drugie się nie powiedzie.
Jeśli naprawdę potrzebujesz przygotowanych transakcji, czytaj dalej.
Odnośnie twojego schematu - dla wygody użyłbym generatorów sekwencji i klauzuli RETURNING po stronie bazy danych.
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,
...
);
Teraz będziesz potrzebować zewnętrznego kleju - koordynatora transakcji rozproszonych (?) - aby to działało poprawnie.
Sztuczka polega na użyciu PRZYGOTUJ TRANSAKCJĘ
zamiast COMMIT
. Następnie po pomyślnym zakończeniu obu transakcji użyj POTWIERDZENIE PRZYGOTOWANO
.
Weryfikacja koncepcji PHP znajduje się poniżej.
OSTRZEŻENIE! w tym kodzie brakuje krytycznego część - czyli kontrola błędów. Dowolny błąd w $db2
powinien zostać przechwycony i ROLLBACK PREPARED
powinien być wykonywany na $db1
Jeśli nie złapiesz błędów, opuścisz $db1
z zamrożonymi transakcjami, co jest naprawdę złe.
<?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'" );
}
?>
I znowu – zastanów się, zanim go użyjesz. To, co proponuje Erwin, może być bardziej rozsądne.
Aha i jeszcze jedna uwaga... Aby korzystać z tej funkcji PostgreSQL, musisz ustawić max_prepared_transactions
zmienna konfiguracyjna na wartość niezerową.