Postgres supporta le transazioni nidificate, ma differiscono dall'SQL convenzionale, più simili alle transazioni con punti parziali nidificati.
Al livello più alto hai sempre il tipico BEGIN/COMMIT/ROLLBACK
, e sui livelli nidificati devi usare i seguenti comandi:
SAVEPOINT name
- crea un nuovo savepoint, con nome univoco per la transazioneRELEASE SAVEPOINT name
- esegue il commit del punto di salvataggio, anche se persisterà solo se la transazione contenente il commitROLLBACK TO SAVEPOINT name
- ripristina il punto di salvataggio
Dovresti anche assicurarti che:
- I nomi utilizzati per ogni
SAVEPOINT
sono unici; - Fallimento in un
SAVEPOINT
viene propagato verso l'alto fino al livello superiore.
L'ultimo bit è un po' complicato, a meno che tu non utilizzi una libreria che possa farlo automaticamente per te.
Quando ho scritto pg-promise, mi sono assicurato che queste due disposizioni fossero garantite:
- Genera automaticamente i nomi dei punti di salvataggio, come
level_1
,level_2
, e così via, in base al livello di transazione; - Esegue contenente
ROLLBACK TO SAVEPOINT name
, più ilROLLBACK
di livello superiore nel caso in cui una transazione figlio fallisca, il tutto basato sulla logica di concatenamento standard.
Vedi anche le limitazioni delle transazioni annidate di PostgreSQL spiegate...