Transazioni all'interno di una Transazione


18

Quale comportamento sarebbe PostgreSQL se, ad esempio, venisse chiamato lo script seguente

BEGIN;
SELECT * FROM foo;
INSERT INTO foo(name) VALUES ('bar');
BEGIN; <- The point of interest
END;

PostgreSQL avrebbe scartato il secondo BEGINo sarebbe stato implicitamente deciso un commit e avrebbe eseguito il BEGIN ENDblocco alla fine come una transazione separata?

Risposte:


13

Ciò di cui avresti bisogno è una cosiddetta "transazione autonoma" (una funzionalità fornita da Oracle). A questo punto questo non è ancora possibile in PostgreSQL. Tuttavia, è possibile utilizzare SAVEPOINT :

BEGIN;
INSERT ...
SAVEPOINT a;
some error;
ROLLBACK TO SAVEPOINT a;
COMMIT;

Non è una transazione completamente autonoma, ma consente di ottenere "ogni transazione" corretta. Puoi usarlo per ottenere ciò che ti aspetti da transazioni autonome.

Altrimenti non ci sono altre soluzioni ragionevoli a questo punto.


13

Puoi provarlo tu stesso:

ATTENZIONE: è già in corso una transazione

Non avvia alcuna nuova (sotto) transazione poiché le transazioni nidificate non sono implementate in PostgreSQL. (Puoi fare un po 'di magia in una pl/pgsqlfunzione, ad esempio, che imita quel comportamento).

Con PostgreSQL 11, si potrebbe pensare che le nuove procedure memorizzate reali e la loro capacità di gestire le transazioni renderebbero possibili transazioni nidificate. Tuttavia, secondo la documentazione , questo non è il caso:

Nelle procedure invocate dal CALLcomando, nonché in blocchi di codice anonimi ( DOcomando), è possibile terminare le transazioni utilizzando i comandi COMMITe ROLLBACK. Una nuova transazione viene avviata automaticamente al termine di una transazione utilizzando questi comandi, quindi non esiste un comando START TRANSACTION separato.


9

PostgreSQL non supporta le sub-transazioni, ma la SAVEPOINTfunzione può rispondere efficacemente alle tue esigenze. Citando dalla documentazione per Advanced access layer a PG tramite le promesse di Vitaly Tomilov su GitHub:

PostgreSQL non ha un supporto adeguato per le transazioni nidificate, supporta solo rollback parziali tramite punti di salvataggio all'interno delle transazioni. La differenza tra le due tecniche è enorme, come spiegato ulteriormente.

Il supporto adeguato per le transazioni nidificate significa che il risultato di una sub-transazione riuscita non viene ripristinato quando viene ripristinata la transazione principale. Ma con i punti di salvataggio PostgreSQL, se si esegue il rollback della transazione di livello superiore, viene eseguito anche il rollback del risultato di tutti i punti di salvataggio interni.

I punti di salvataggio possono essere utilizzati per rollback parziali a un punto precedente all'interno di una transazione attiva. Ad esempio, per stabilire un punto di salvataggio e successivamente annullare gli effetti di tutti i comandi eseguiti dopo che è stato stabilito:

BEGIN;
    INSERT INTO table1 VALUES (1);
    SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (2);
    ROLLBACK TO SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (3);
COMMIT;

La transazione precedente inserirà i valori 1 e 3, ma non 2. Consultare la SAVEPOINTdocumentazione per ulteriori informazioni.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.