martedì 23 dicembre 2008

database, thread e transazioni

Proprio in questi giorni a lavoro mi sono imbattuto in un problema non banale riguardo le transazioni dei database.
Avevo 2 thread A che scriveva su db e B che doveva leggere il dato.
Nel mio flusso ideale la cosa avrebbe dovuto funzionare così


invece dopo qualche ora spesa a cercare di capire come mai B fallisse sempre a leggere i dati e dopo aver controllato l'access log mi sono accorto che B leggeva i dati prima che A li avesse scritti!

quindi succedeva che


Visto che l'ordine di esecuzione non poteva essere previsto ho dovuto creare in B un meccanismo che tentasse di leggere il dato più volte o fino a soddisfare la lettura, o fino a raggiungere un numero massimo di tentativi ed uscire con errore.

quindi ho fatto una cosa del genere


Ma qui sono successe cose sinistre.

Infatti dall'access log risultata che A aveva scritto il dato mentre B che aveva iniziato a leggerlo precedentemente falliva anche quando A aveva terminato la sua scrittura.
Grazie all'aiuto dei miei colleghi più esperti mi è stato spiegato che B iniziava la sua transazione prima della fine della scrittura da parte di A e B, per consistenza, manteneva lo stato iniziale di fallimento di ricerca del dato. Quindi anche se avessi letto quel valore per ore dopo che A lo aveva scritto avrei sempre trovato la situazione iniziale della base dati ovvero nessun dato trovato!



Armato di sana pazienza e spulciando la documentazione del DB (mysql in questo caso ma tutti i moderni db con supporto alla transazioni hanno l'equivalente istruzione) ho trovato alla fine il comando che disabilita questo comportamento ovvero:

set transaction isolation level read committed;

Con questo comando B è stato in grado di accorgersi quando il dato è divenuto disponibile ed io ho risolto il mio gravoso problema.