sql >> Base de Datos >  >> RDS >> PostgreSQL

Postgresql:PREPARAR TRANSACCIÓN

Sí, es posible, pero ¿realmente lo necesitas?

Piénselo dos veces antes de decidir que realmente deben ser dos bases de datos separadas.

Simplemente puede mantener ambas conexiones abiertas y RETROCEDER el primer comando si falla el segundo.

Si realmente necesita transacciones preparadas, continúe leyendo.

Con respecto a su esquema, usaría generadores de secuencias y la cláusula RETURNING en el lado de la base de datos, solo por conveniencia.

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,
  ...
);

Ahora necesitará un poco de pegamento externo (coordinador de transacciones distribuidas (?)) para que esto funcione correctamente.

El truco es usar PREPARE TRANSACTION en lugar de COMMIT . Luego, después de que ambas transacciones tengan éxito, use COMMIT PREPARED .

La prueba de concepto de PHP se encuentra a continuación.

¡ADVERTENCIA! a este código le falta el crítico parte - eso es control de errores. Cualquier error en $db2 debe ser capturado y ROLLBACK PREPARED debe ejecutarse en $db1 Si no detecta errores, dejará $db1 con transacciones congeladas, lo cual es muy, muy malo.

<?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'" );
}
?>

Y de nuevo, piense antes de usarlo. Lo que propone Erwin podría ser más sensato.

Ah, y solo una nota más... Para usar esta característica de PostgreSQL, debe configurar max_prepared_transactions variable de configuración a un valor distinto de cero.