Ce face BEGIN, COMMIT, ROLLBACK și SAVEPOINT
În PostgreSQL, fiecare instrucțiune individuală rulează implicit în propria tranzacție (autocommit). Pentru a grupa mai multe operații într-o unitate atomică (totul sau nimic), deschizi un bloc cu BEGIN (sau START TRANSACTION) și îl finalizezi cu COMMIT sau îl anulezi cu ROLLBACK. În PostgreSQL, chiar și comenzile DDL (CREATE TABLE, ALTER TABLE, DROP INDEX) sunt tranzacționale și pot fi anulate cu ROLLBACK!
O particularitate importantă a lui PostgreSQL este că orice eroare SQL apărută în interiorul unui bloc BEGIN marchează întreaga tranzacție ca abortată: comenzile ulterioare vor fi refuzate cu ERROR: current transaction is aborted până la un ROLLBACK sau ROLLBACK TO SAVEPOINT.
Clauze, operatori și argumente
| Clauză / Operator | Descriere |
|---|---|
BEGIN [ISOLATION LEVEL ...] |
Deschide o tranzacție nouă (niveluri: READ COMMITTED implicit, REPEATABLE READ, SERIALIZABLE). |
COMMIT |
Salvează permanent toate modificările efectuate în tranzacția curentă. |
ROLLBACK |
Anulează toate modificările făcute de la BEGIN și readuce baza de date la starea inițială. |
SAVEPOINT nume_punct |
Creează un punct de control în interiorul tranzacției curente. |
ROLLBACK TO SAVEPOINT nume |
Anulează doar modificările efectuate după acel SAVEPOINT și curăță starea de eroare a tranzacției. |
Exemple
Exemplul 1: Transfer bancar atomic între două conturi cu BEGIN și COMMIT
Scădem 500 RON dintr-un cont și îi adăugăm în altul; ambele modificări devin vizibile simultan doar la COMMIT.
BEGIN;
UPDATE conturi SET sold = sold - 500.00 WHERE id = 10;
UPDATE conturi SET sold = sold + 500.00 WHERE id = 20;
INSERT INTO jurnal_transferuri (sursa_id, destinatie_id, suma)
VALUES (10, 20, 500.00);
COMMIT;
Rezultat interogare
BEGIN
UPDATE 1
UPDATE 1
INSERT 0 1
COMMIT
Exemplul 2: Recuperarea dintr-o eroare fără pierderea întregii tranzacții folosind SAVEPOINT
Creăm o comandă, apoi încercăm să aplicăm un cupon; dacă apare o constrângere încălcată, revenim cu ROLLBACK TO SAVEPOINT și păstrăm comanda validă.
BEGIN;
INSERT INTO comenzi (id, client_id, total_lei) VALUES (6001, 101, 250.00);
SAVEPOINT inainte_de_cupon;
-- Această operație poate eșua (ex: cupon expirat sau cheie duplicată)
INSERT INTO cupoane_folosite (comanda_id, cod_cupon) VALUES (6001, 'EXPIRAT');
-- În caz de eroare, revenim la savepoint și continuăm tranzacția:
ROLLBACK TO SAVEPOINT inainte_de_cupon;
COMMIT;
Rezultat interogare
BEGIN
INSERT 0 1
SAVEPOINT
ERROR: check constraint "cupon_activ_chk" is violated
ROLLBACK
COMMIT
Greșeli frecvente
- Uitatul unei tranzacții deschise în starea
idle in transaction: aceasta blochează procesulVACUUMsă curețe rândurile moarte și păstrează lacătele active; configureazăidle_in_transaction_session_timeoutîn producție. - Încercarea de a rula alte interogări după o eroare fără
ROLLBACK TO SAVEPOINT: în PostgreSQL, chiar dacă trimițiCOMMITla finalul unei tranzacții cu eroare, Postgres execută automat unROLLBACK.
Comenzi și funcții înrudite
INSERT INTO ... RETURNING: Inserează unul sau mai multe rânduri și returnează imediat valorile generate (ID-uri, timestamp-uri) fără o interogare suplimentară.ON CONFLICT DO UPDATE (UPSERT): Rezolvă atomic conflictele de cheie unică la inserare: ignoră rândul duplicat sau îl actualizează pe loc.DELETE ... USING și TRUNCATE: Șterge rânduri filtrate prin joncțiuni cu DELETE … USING sau golește instantaneu tabele întregi cu TRUNCATE.