andbin ha scritto:
iBaffiPro ha scritto:
Read Committed: non garantisce che un dato letto continui ad essere presente oppure assente dopo il commit;
Repeatable Read: garantisce che i record letti restino invariati dopo il commit ma gli altri record della tabella possono cambiare
Serializable: garantisce che la tabella nella quale si legge il record resti invariata dopo il commit
NOO. Leggi bene le spiegazioni che trovi online sulle 3 "anomalie": Dirty reads, Non-repeatable reads e Phantom reads.
Non stare, per ora, a guardare COSA viene usato (snapshot, lock, ecc...) per impedire queste anomalie, perché DBMS differenti potrebbero usare tecniche o approcci (leggermente) differenti.
È importante invece capire COSA avviene in ciascuna anomalia. Poi banalmente c'è la tabellina che ti dice quali anomalie sono permesse e non permesse per ciascun livello di isolamento.
P.S. ma il Dirty reads l'ho spiegato prima! .. e credo pure bene ....
iBaffiPro ha scritto:
Quello che mi stai dicendo e che dovrei dedicare più tempo ed attenzione a questo aspetto e scegliere @Transaction diverse per @Service diverse e non generalizzare come sto facendo? Giusto?
Per me, puoi anche mettere Serializable su tutte le tue transazioni .... l'importante è che concludi queste esercitazioni prima possibile ...
Mi sono sbagliato a scrivere, volevo usare "uncommitted". Approfondisco il discorso con un esempio:
BEGIN TRANSACTION;
SELECT * FROM Tabella_A;
SELECT * FROM Tabella_A;
COMMIT;
Questo è quello che ho capito:
Read uncommitted: le 2 select possono fornire dati diversi e dopo il commit i dati possono essere diversi dalla seconda select (la transazione non fallisce mai);
Read committed: la seconda select può fornire dati diversi dalla prima e dopo il commit i dati devono essere gli stessi della seconda select, in caso contrario la transazione fallisce e non fornisce nulla. Tra la prima e la seconda select si possono aggiungere, modificare o rimuovere record alla tabella.
Repeatable read: come read committed la seconda select deve essere rispettata, dopo il commit i dati letti devono essere presenti a DB, ma rispetto a read committed garantisce che i dati letti nella prima select siano presenti anche nella seconda. Nella seconda select possono esserci più dati rispetto alla prima ma non in meno e i dati della prima select devono essere presenti anche nella seconda;
Serializable: garantisce che i dati della prima select, della seconda e dopo il commit siano identici.
Il livello di isolamento chiamato read uncommitted permette i dirty reads mentre invece l'isolamento chiamato read committed non li permette.
In PostgreSQL il read uncommitted non è gestito e, se settato, si comporta come read committed. Questo significa che in PostgreSQL i dirty reads non sono mai possibili. Su altri database invece il read uncommitted è gestito e settabile.
In merito all'isolation level nelle transazioni su DB ci sono 3 tipi di "anomalie" che possono avvenire. Sono denominate:
- Dirty reads (letture sporche): la transazione A legge dei record inseriti da una transazione B non ancora conclusa che fallendo lancia un rollback e cancella gli stessi record letti dalla transazione A. In sostanza la transazione A fornisce dei record che a DB non esistono. Ovviamente la problematica si verifica non solo per nuovi inserimenti ma anche per nuove modifiche o cancellazioni di record;
- Non-repeatable reads (letture non ripetibili): Una lettura non ripetibile si verifica quando, nel corso di una transazione, una riga viene recuperata due volte e i valori all'interno della riga differiscono tra le letture. Come spiegato sopra read uncommitted (non supportato in PostgreSQL), read committed, repeatable read e serializable forniscono soluzioni diverse.
- Phantom reads (letture fantasma): Una lettura fantasma si verifica quando, nel corso di una transazione, nuove righe vengono aggiunte o rimosse da un'altra transazione ai record letti. Come spiegato sopra read uncommitted (non supportato in PostgreSQL), read committed, repeatable read e serializable forniscono soluzioni diverse.
Ritornando al mio esempio:
Dirty reads non ne posso avere perché uso PostgreSQL, non-repeatable reads e phantom reads neppure perché ho solo 1 select quindi qualunque transazione (la meno bloccante, onerosa, ecc... ovviamente) può andare bene, quindi la seguente:
@Transactional(
isolation = Isolation.READ_COMMITTED,
propagation = Propagation.REQUIRED,
rollbackFor = Exception.class,
readOnly=false
)
a mio avviso può andare bene. Ho messo Propagation.REQUIRED perché in realtà ho scoperto di avere una transazione in più interna alla fase di registrazione che mi era sfuggita. In pratica una transazione che si occupa di verificare se la fase di registrazione è resa possibile oppure no.
Concordi su tutto? Ho più o meno capito e posso dedicarmi alle altre @Service oppure no?
P.S.: Avevo letto che SQL Server usava di default serializable ma evidentemente ho letto una stupidaggine.