PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Postgresql:PREPARAR TRANSAÇÃO


Sim, é possível, mas você realmente precisa disso?

Pense duas vezes antes de decidir que realmente devem ser dois bancos de dados separados.

Você pode apenas manter as duas conexões abertas e ROLLBACK o primeiro comando se o segundo falhar.

Se você realmente precisa de transações preparadas, continue lendo.

Em relação ao seu esquema - eu usaria geradores de sequência e cláusula RETURNING no lado do banco de dados, apenas por conveniência.
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,
  ...
);

Agora você precisará de alguma cola externa - coordenador de transações distribuídas (?) - para fazer isso funcionar corretamente.

O truque é usar PREPARE TRANSACTION em vez de COMMIT . Depois que ambas as transações forem bem-sucedidas, use COMMIT PREPARED .

A prova de conceito do PHP está abaixo.

AVISO! este código não tem o crítico parte - que é o controle de erros. Qualquer erro em $db2 deve ser capturado e ROLLBACK PREPARED deve ser executado em $db1 Se você não pegar erros, você deixará $db1 com transações congeladas, o que é muito, muito ruim.
<?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'" );
}
?>

E novamente - pense antes de usá-lo. O que Erwin propõe pode ser mais sensato.

Ah, e só mais uma observação... Para usar esse recurso do PostgreSQL, você precisa definir max_prepared_transactions config variável para valor diferente de zero.