Newsgroup: it.comp.java
Titolo: Problemi di concorrenza

Ciao a tutti,
sto sviluppando un'applicazione web con jsp per la mia tesi di laurea e mi
ritrovo ad avere un problema di concorrenza sull'accesso ad alcune tabelle
del db (il db è oracle e utilizzo jdbc per le connessioni).
La situazione è questa:
ogni utente apre una propria sessione e, all'interno della propria sessione,
una propria connessione al db;
l'utente X deve fare una select su alcuni record di una tabella A e, in base
ai risultati acquisiti, deve fare una insert sulla stessa tabella. Questa
operazione (select + insert) deve essere atomica, nel senso che nel
frattempo nessuno deve poter leggere o scrivere quei record acquisiti in
lettura su A finchè non è stata eseguita la scrittura del nuovo record.
Il tutto dovrebbe essere fatto senza fare un lock sull' intera tabella,
perchè se invece un altro utente Y volesse solo leggere altri record da A,
oppure leggere altri record da A e fare una insert in base a questi,
dovrebbe poterlo fare in qualunque momento.
Ho letto parecchia documentazione su metodi synchronized, su transaction
isolation ecc. ecc. ma ho le idee molto confuse e non riesco a trovare una
soluzione valida.
Qualcuno di voi può aiutarmi?...vanno bene anche link a documenti che
potrebbero essermi utili.
Grazie
Letizia

Non č che mi voglio rispondere da sola ..č' solo per non creare un altro
thread :))
Comunque volevo dire che l'unica cosa che mi č venuta in mente č questa:
conn.setAutoCommit(false);
SELECT  * FROM tabellaA WHERE .....FOR UPDATE;
//elabora questi risultati
INSERT INTO tabellaA ...
conn.commit()
//o rollback se qualcosa va male
Ma non sono certa che possa funzionare.
Supponendo di aver istruito Oracle a lockare i record acquisiti in R/W,
č sicuro che il lock sui record selezionati dalla SELECT resta fino al
commit? E, se sě, chi aspetta che il lock venga rilasciato non va avanti
spero...non viene eseguita nessun'altra istruzione giusto?
Letizia

 
Sei sicura di non poter gestire il tutto con un algoritmo "ottimistico"?
Nel senso:
- acquisisci i dati (senza lockare)
- fai i tui calcoli
- fai l'insert controllando che i dati acquisiti siano ancora validi (ad 
esempio con un timestamp), altrimenti sollevi un'eccezione, rileggi i 
dati o qualsiasi altro comportamento valido per la tua app.
La gestione "pessimistica" di lockare il tutto durante la sessione del 
client e' infatti deleteria e non scala. Se non sei costretta (e' raro 
che sia cosi'), evitala
uL

 ha scritto nel messaggio > Sei


 Letizia
Si, e' un caso tipico. Si puo' tranquillamente fare con la gestione 
ottimistica, l'unica cosa e' che ti potrebbero "rubare" la prenotazione 
fino all'ultimo, ossia alla conferma finale. Che e' poi come succede 
nella realta' nella maggior parte dei sistemi di prenotazione.
La soluzione "pessmistica" ha un sacco di contro: per esempio, che 
succede se l'utente fa la select e poi si alza e si va a fare una doccia 
prima di confermare?
ciao
uL

 ha scritto nel messaggio
news:3DA8A011...@flashnet.it...


 Letizia
E se:
- la seconda pagina non trova piu' il record perche' mentre lui ci 
pensava (fra la prima e la seconda) qualcun'altro ha fatto la 
transazione completa?
- fra la seconda pagina e il submit finale sente che un autogol ha 
permesso alla nazionale di sperare ancora e va a sentire il servizio in tv?
ciao
uL

 uL
Ciao
Letizia

 qualcuno si è già prenotato-->peggio per te che 6 andato a farti la doccia)
Allora basta inserire il tutto in una transazione e fare in modo che il 
DB abbia il giusto livello di isolamento (il default di Oracle va bene)
BTW, questa *e'* una gestione ottimistica .
ciao
uL

 uL
Buonanotte
Letizia

 Volevo solo sapere se è corretto per i miei scopi...
Ti consiglio di dare un occhiata anche agli EJB. Forse potrebbero essere
utili. E poi sconsiglio vivamente un bean in sessione con una connessione
aperta al db, ma piuttosto un connection pool (quindi un factory di
connessioni che si appoggia ad un DataSource).
dai uno sguardo qui per farti un idea:
http://www.javaportal.it/j2eelibro.htm
Poi passa ai tutorial della sun:
http://java.sun.com/j2ee/
Ciao ed in bocca al lupo per la laurea.
Giuseppe

 Giuseppe
Crepi il lupo.
Ciao, Letizia

 Mi sono spiegata ora? Oppure sono io che non capisco?.....
... č infatti un problema risolvibile gestendo il tutto con EJB e settando
opportunamente il livello d'isolamento della transazione
Ma per l'uso che ne devi fare (ovvero una tesi) la tua soluzione puņ andare
benissimo
Ciao e riposta se hai problemi
Giuseppe

 
Quello che descrivi nelle righe di codice di sopra è una sessione di 
lavoro con il database che consiste nell'eseguire le tue istruzioni 
(select, delete update e insert) in una sorta di ambiente separato dagli 
altri utenti attualmente connessi al db.
In praticha fino a quando non esigui un commit, i record inseriti nel db 
li vedi solo tu, quelli cancellati non sono realmente cancellati etc.
Se esigui un rollback ogni cosa ritorna alla situazione precedente 
all'inizio della sessione.
Altra cosa è invece il livello di isolamento che diverse sessioni hanno 
fra loro. Quando modifichi un record questo può comportare diversi tipi 
di lock a seconda del livello di isolamento:
pescando direttamente dalla documentazione su JDBC (visto che stai 
usando proprio JDBC per connetteri ad un database)
static int TRANSACTION_NONE	Indicates that transactions are not upported.
static int TRANSACTION_READ_COMMITTED           Dirty reads are 
revented; non-repeatable reads and phantom reads can occur.
static int TRANSACTION_READ_UNCOMMITTED           Dirty reads, 
non-repeatable reads and phantom reads can occur.
static int TRANSACTION_REPEATABLE_READ           Dirty reads and 
non-repeatable reads are prevented; phantom reads can occur.
static int TRANSACTION_SERIALIZABLE           Dirty reads, 
non-repeatable reads and phantom reads are prevented.
Quelli di sopra sono i valori da passare al metodo 
setTransactionIsolation di una connect e determinano cosa possono fare 
gli altri utenti dopo che tu hai modificato il contenuto di una tabella.
Come puoi facilmente dedurre si va da un blocco della tabella alla 
possibilità di leggere record che sono già cancellati da te (prima del 
commit).
Non tutti i driver jdbc e/o i database supportano tutti i diversi 
modelli di isolamento. Credo che Oracle li supporti tutti ma non sono 
sicuro che il protocollo thin si, forse sarai costretta ad usare oci8.
Puoi effettuare dei test con il metodo
supportsTransactionIsolationLevel(int) di DatabaseMetaData.
Spero di esserti stato utile.
Una curiosità: quale facoltà?
-- 
Fabio Ambrosanio
/quousque tandem/

 Ciao e riposta se hai problemi
Una domanda ce l'avrei:
Supponiamo che Gino locki in R/W (SELECT FOR UPDATE) 3 records e Pippo locki
nello stesso momento altri 5 records ovviamente diversi dai precedenti.
Arriva Pluto e vuole fare una semplice SELECT su un record dei 3 lockati da
Pino e un record dei 5 lockati da Pippo:
Come fa ad ottenerli? Deve aspettare che sia Gino che Pippo abbiano finito
entrambi? Non si rischiano attese troppo lunghe?
Grazie per la tua disponibilità e per quella di chiunque vorrà rispondermi
Letizia

 Una curiosità: quale facoltà?
Ing. Informatica Politecnico di Torino
Ciao, Letizia

 nodale della questione...
Le modifiche (insert update e delete) apportate durante una transazione 
sono viste solo all'interno della transazione stessa, per cui tu puoi 
tranquillamente modificare dei record e poi eseguire delle select e 
magari poi fare rollback senza che gli altri utenti connessi al db 
vedano i risultati delle tue operazioni.
Ovviamente a seconda del livello si isolamento blocchi la tabella, solo 
dei record e niente :-)
Ciao


 Fabio Ambrosanio
Grazie mille Fabio  :)
Ciao,
Letizia

 interessava solo sapere se può funzionare questo sistema
E stai facendo una tesi di laurea? :-)
A parte gli scherzi, il punto che Ugo cercava di far passare e' che il tuo 
problema e' un'istanza specifica di un problema generale molto noto e gia' 
risolto. 
Una volta compreso il problema, e le due soluzioni, con vantaggi e 
svantaggi, diventi perfettamente in grado di decidere da sola se il tuo 
codice (e la soluzione che il codice rappresenta) e' adatta o no.
Nello specifico, si', il sistema puo' funzionare.
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

 Nello specifico, si', il sistema puo' funzionare.
Ok questo era ciò che mi serviva sapere.
Grazie anche a te
Letizia

 
Allora non avevo capito cosa non avevi capito... :)
BTW, se tu avessi ben capito, non avresti chiesto perche' il tuo codice 
avrebbe o meno dovuto funzionare :p
BTW-again, si, il tuo codice funziona ma dipende dal livello di 
isolamento del DB. Inoltre - livello di isolamento a parte - non puo' 
essere indipendente dal DB proprio perche' non vuoi usare - come *credo* 
di aver capito - un livello di astrazione piu' alto (gli EJB) e stai 
facendo tutto a livello di JDBC "a manina". Che, per la cronaca, e' 
comunque j2ee... (usare servlet, jsp e jdbc e' comunque usare j2ee, non 
devi per forza usare gli ejb)
Riassumendo, visto che hai parlato di indipendenza dal DB: cosi' com'e', 
il tuo codice funziona a seconda del livello di isolamento del DB e a 
seconda del DB, poiche' per esempio la SELECT FOR UPDATE non tutti la 
supportano (due livelli di incertezza).
Se usassi gli EJB, dipenderebbe invece solo dal livello di isolamento 
del DB. Da quello che *credo* tu voglia fare dagli ultimi post che hai 
mandato, dovresti evitare anche gli "unrepeatable read".
Se vuoi essere completamente indipendente, non puoi :)
ciao
uL

 dei record e niente :-)
Questo pero' e' l'effetto e non la causa: a seconda del livello di 
isolamento sei o meno isolato dai vari problemi di "dirty read", 
"unrepeatable read", ecc. Il DB per isolarti (sempre se supporta il 
livello di isolamento, altrimenti nisba) potrebbe utilizzare dei lock a 
livello di tabella, record, ecc.
Una diuscussione molto ben fatta sui vari tipi di problematiche (ad 
esempio perche' in EJB non e' stata prevista un'astrazione sul livello 
di isolamento) si trova su "Mastering EJB" di Ed Roman, downloadabile da 
www.theserverside.com
ciao
uL

 uL
Ciao,
ti farò sapere come si evolverà questa vicenda
Letizia

 Letizia
In bocca al lupo per la tesi.
ciao
uL