Да, възможно е, но наистина ли ви трябва?
Помислете два пъти, преди да решите, че това наистина трябва да са две отделни бази данни.
Можете просто да държите двете връзки отворени и да ROLLBACK първата команда, ако втората е неуспешна.
Ако наистина имате нужда от подготвени транзакции, продължете да четете.
Относно вашата схема - бих използвал генератори на последователности и клауза 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,
...
);
Сега ще ви трябва малко външно лепило - координатор на разпределени транзакции (?) - за да работи правилно.
Номерът е да използвате ПОДГОТВЯНЕ НА ТРАНЗАКЦИЯ
вместо КОМИТ
. След това, след като и двете транзакции успеят, използвайте COMMIT PREPAREDкод>
.
PHP доказателство за концепцията е по-долу.
ПРЕДУПРЕЖДЕНИЕ! в този код липсва критичното част - това е контрол на грешките. Всяка грешка в $db2
трябва да бъде уловен и ПОДГОТВЕН ЗА ВЪРТАНЕ
трябва да се изпълни на $db1
Ако не улавяте грешки, ще напуснете $db1
със замразени транзакции, което е наистина, наистина лошо.
<?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'" );
}
?>
И отново - помислете преди да го използвате. Това, което Ервин предлага, може да е по-разумно.
О, и само още една бележка... За да използвате тази функция на PostgreSQL, трябва да зададете max_prepared_transactions
конфигурационната променлива на ненулева стойност.