Nel nostro corso vedremo le transazioni per ben tre volte. E ogni volta scopriremo qualcosa di nuovo. Ora impariamo le basi delle transazioni. Nella seconda parte del corso ci occuperemo dei livelli di isolamento delle transazioni, e alla fine — delle sfumature delle transazioni annidate.
Cos'è una transazione
Partiamo dal semplice — la definizione. Una transazione è un gruppo di azioni che vengono eseguite solo tutte insieme. Tutto qui.
Da questo segue una cosa importante: se durante l'esecuzione di una qualsiasi azione del gruppo succede un errore, bisogna annullare il risultato di tutte le altre azioni e riportare il sistema allo stato iniziale.
Dal punto di vista di SQL, una transazione è un insieme di azioni (tipo insert, update o delete di dati), che garantisce che o tutte le operazioni dentro la transazione vanno a buon fine, oppure nessuna viene eseguita. Questo comportamento rende il lavoro con i database affidabile e coerente, soprattutto in scenari critici come la gestione dei pagamenti o l'aggiornamento di dati collegati.
Pensa a quando trasferisci soldi tra due conti bancari. Se semplifichiamo, abbiamo due operazioni in sequenza:
- Dal primo conto viene prelevata una somma.
- Sul secondo conto viene accreditata la stessa somma.
Se succede un errore proprio alla fine (tipo il server crasha), è importante che nessun utente ci rimetta. In altre parole, o entrambi i passaggi vanno a buon fine (la transazione viene confermata), oppure entrambi vengono annullati (la transazione viene cancellata).
Transazioni e principi ACID
Le transazioni si basano sui principi ACID, che ci ricordano quattro caratteristiche chiave:
- Atomicity (Atomicità): tutto o niente. O tutte le operazioni dentro la transazione vengono eseguite, oppure vengono annullate.
- Consistency (Coerenza): i dati restano in uno stato corretto prima e dopo la transazione.
- Isolation (Isolamento): ogni transazione lavora come se fosse l'unica nel sistema.
- Durability (Durabilità): dopo la conferma i dati restano salvati, anche se il server crasha.
Comandi base per gestire le transazioni
Ora preparati alla pratica! Ecco i tre comandi principali per gestire le transazioni:
BEGIN
Inizia una nuova transazione. Tutte le operazioni successive saranno eseguite al suo interno.COMMIT
Conferma le modifiche. Dopo questo comando tutte le azioni diventano permanenti.ROLLBACK
Annulla le modifiche. Se qualcosa va storto, puoi annullare la transazione e i dati restano come prima.
Sintassi base delle transazioni
Struttura semplice di una transazione:
BEGIN;
-- qui vanno le tue operazioni SQL
COMMIT;
Esempio di uso di ROLLBACK:
BEGIN;
-- modifica della tabella studenti
UPDATE students
SET grade = grade + 10
WHERE id = 1;
-- Oh! Ci siamo accorti che era un errore.
ROLLBACK;
Esempio di uso di una transazione in un caso reale
Supponiamo di avere queste tabelle:
students:
| id | name | grade |
|---|---|---|
| 1 | Otto Lin | 85 |
| 2 | Anna Song | 90 |
courses:
| course_id | course_name |
|---|---|
| 1 | Matematica |
| 2 | Storia |
Mettiamo che vogliamo iscrivere uno studente a un corso e aggiornare il suo voto medio nello stesso momento:
BEGIN;
-- Passo 1: Aggiungiamo una riga nella tabella "iscrizioni ai corsi"
INSERT INTO course_enrollments (student_id, course_id)
VALUES (1, 2);
-- Passo 2: Aggiorniamo il voto medio dello studente
UPDATE students
SET grade = grade + 5
WHERE id = 1;
COMMIT;
Cosa succede se il server crasha tra il primo e il secondo passo? Se non usassimo una transazione, i dati sarebbero incoerenti: l'iscrizione al corso viene aggiunta, ma il voto medio non viene aggiornato. Con la transazione invece, o entrambe le operazioni vanno a buon fine o entrambe vengono annullate.
Gestione degli errori dentro le transazioni
A volte qualcosa va storto e dobbiamo gestire bene l'errore. In PostgreSQL la transazione viene annullata automaticamente se succede un errore.
Facciamo un errore apposta e vediamo cosa succede. Immagina che abbiamo un vincolo di unicità sulla colonna student_id nella tabella course_enrollments. Proviamo ad aggiungere una riga duplicata:
BEGIN;
INSERT INTO course_enrollments (student_id, course_id)
VALUES (1, 2);
-- FINE DELLA TRANSAZIONE (non ancora eseguita)
COMMIT;
Se provi a inserire uno studente già iscritto al corso, si verifica un errore e PostgreSQL annulla automaticamente la transazione.
Uso di ROLLBACK per annullare manualmente
Spesso non puoi prevedere gli errori e vuoi annullare la transazione se qualcosa va storto:
BEGIN;
-- Aggiungiamo un nuovo studente
INSERT INTO students (name, grade)
VALUES ('Omori Sanny', 75);
-- Ops! Ci siamo accorti che lo studente è stato aggiunto per sbaglio.
ROLLBACK;
Dopo il comando ROLLBACK la tabella resta invariata — Omori Sanny non appare in students.
Consigli utili ed errori tipici
Lavorare con le transazioni è più facile se ricordi alcune regole importanti:
- Usa sempre le transazioni se la tua operazione ha più di un passaggio, soprattutto se modifichi dati in più tabelle.
- Non dimenticare mai di confermare le modifiche (
COMMIT). Altrimenti la transazione resta aperta e i dati non cambiano. - Racchiudi le operazioni complesse in una transazione per mantenere la coerenza dei dati.
- Se vedi un errore in qualsiasi punto, non aver paura di usare
ROLLBACK.
Ora che sai come controllare le operazioni con le transazioni, è il momento di mettere in pratica queste conoscenze e passare a studiare le transazioni per garantire l'integrità dei dati!
GO TO FULL VERSION