sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgresql:FÖRBERED TRANSAKTION

Ja det är möjligt, men behöver du verkligen det?

Tänk efter två gånger innan du bestämmer dig för att detta verkligen måste vara två separata databaser.

Du kan bara hålla båda anslutningarna öppna och ROLLBACK det första kommandot om det andra misslyckas.

Fortsätt läsa om du verkligen behöver förberedda transaktioner.

Angående ditt schema - jag skulle använda sekvensgeneratorer och RETURNING-satsen på databassidan, bara för bekvämlighets skull.

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

Nu behöver du lite externt lim - distribuerad transaktionskoordinator (?) - för att få detta att fungera korrekt.

Tricket är att använda FÖRBERED TRANSAKTION istället för COMMIT . Sedan efter att båda transaktionerna har lyckats, använd COMMIT REPARED .

PHP proof-of-concept finns nedan.

VARNING! den här koden saknar kritiska del - det är felkontroll. Eventuella fel i $db2 ska fångas upp och ÅTERBAKNING FÖRBEREDAS bör köras på $db1 Om du inte upptäcker fel lämnar du $db1 med frysta transaktioner vilket är riktigt, riktigt dåligt.

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

Och återigen - tänk efter innan du kommer att använda den. Det Erwin föreslår kan vara mer förnuftigt.

Åh och bara en anteckning till... För att använda den här PostgreSQL-funktionen måste du ställa in max_prepared_transactions konfigurationsvariabel till ett värde som inte är noll.



  1. Jag förstår inte hur postgresqls nextval() fungerar, kan någon förklara?

  2. Hur använder man session på webbsidor?

  3. Aggregera funktioner över arrayer

  4. Hur man kör Raw SQL i SQLAlchemy