Premetto che cercherò di semplificare al massimo l’ argomento per facilitarne la comprensione il più possibile.
Per prima cosa diciamo cosa è una transazione:
“Una transazione è un insieme parzialmente ordinato di operazioni di lettura e scrittura; essa costituisce l’ effetto dell’ esecuzione di programmi che effettuano le funzioni desiderate dagli utenti”
Perché sono importanti le transazioni?
Perché quando compiamo operazioni su di un database dobbiamo SEMPRE garantire l’integrità dei dati e della struttura oltre a garantire che le operazioni che vengono effettuate su questo vadano a buon fine senza creare incongruenze od errori.
Per chiarire meglio facciamo un semplice esempio.
Supponiamo di operare su di una tabella così strutturata:
Prodotti(IdProdotto, Descrizione, Qta).
Il campo Qta si riferisce alla quantità di prodotto attualmente disponibile a magazzino.
Supponiamo di avere un record simile a questo:
IdProdotto Descrizione Qta
123 Scarpe 10
Abbiamo on-line due clienti, A e B ed entrambi vogliono comprare quel particolare articolo (il cui codice prodotto è123), A ne vuole 3 e B ne vuole 8.
Le operazione che verranno effettuate sul database saranno all’ incirca queste:
SELECT Qta FROM Prodotti WHERE IdProdotto=123 (1)
….
….
//Codice di controllo sulla quantità che non deve essere inferiore a 3
….
….
UPDATE Prodotto SET Qta=Qta-3 WHERE IdProdotto=123 (2)
Vista così potrebbe sembrare corretta, ma cosa succede se ad esempio A e B vengono processati dal sistema contemporaneamente e questo è possibile (sarebbe interessante fare una postilla sui thread ma non è questo il nostro scopo), soprattutto in sistemi di vendita on-line molto frequentati, per non parlare dei sistemi di transazione bancaria.
Succede che A (o meglio il thread A) esegue la query 1 e vede che ci sono dieci articoli disponibili, B esegue anch’ essa la query numero 1 e vede che ci sono 10 articoli disponibili così entrambi fanno il loro ordine. A questo punto A aggiorna il valore di Qta a 7 (10-3) e subito dopo B fa la medesima cosa mettendolo a 2 (10-8).
E’ evidente quale sia il problema, entrambi i thread hanno processato i dati in maniera indipendene generando informazioni sbagliate.
La soluzione consiste nel gestire l’ accesso alle informazioni (quindi alle tabelle) in modo esclusivo.
Come possiamo mettere in pratica questa soluzione?
Utilizzando i meccanismi di LOCK e UNLOCK sulle tabelle.
La sintassi è la seguente:
LOCK TABLES nome_tabella [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, nome_tabella [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES
E’ necessario chiarire il significato delle opzioni di lock, in particolare:
- READ : se un thread ottiene un lock in lettura su di una tabella questo thread e tutti gli altri thread potranno solo leggere dalla tabella
- WRITE :se un thread ottiene un lock in scrittura su di una tabella solo questo thread potrà leggere o scrivere nella tabella, tutti gli altri saranno bloccati
- READ LOCAL : simile al bloccaggio in lettura ma permette ad altri thread di inserire dati
- LOW PRIORITY : questa opzione o attributo si può applicare al lock in scrittura e assegna a tale lock una priorità più bassa rispetto a quello in lettura
Quindi nel nostro caso avremo:
LOCK TABLES Prodotti WRITE;
SELECT Qta FROM Prodotti WHERE IdProdotto=123;
….
….
//Codice che controlla che Qta nonsia minore di 3 ed eventuali altricontrolli
….
….
UPDATE Prodotti SET Qta=Qta-3 WHERE IdProdotto=123;
UNLOCK TABLES;
Ovviamente nessuno Vi vieta di bloccare più tabelle in modalità diverse se fosse necessario.
Questa soluzione per quanto pratica ha uno svantaggio che risiede nel fatto che viene bloccata l’ intera tabella. E questo è uno spreco di risorse, infatti nel nostro caso sarebbe stato sufficiente bloccare il record relativo al prodotto con IdProdotto=123.
Questo è possibile e per farlo è necessario utilizzare le transazioni vere e proprie che permettono operazioni di commit e rollback.
Mi fermo qui perché non so se l’ argomento relativo alle transazioni possa interessare o meno, anche considerando che per la maggior parte di noi (almeno penso) questi meccanismi dovrebbero essere sufficienti.
Ciao a tutti, Mc