Newsgroup: it.comp.programmare.win32
Titolo: Gestione accessi concorrenti al database

Ciao a tutti.
Vorrei qualche consiglio sulla politica da adottare nello sviluppo di 
un'applicazione per gestire gli accessi concorrenti di piu' utenti allo stesso 
database nell'ambito di un'architettura di tipo client-server. Il tutto, 
possibilmente, senza doversi necessariamente legare ad uno specifico database.
Grazie per l'attenzione
Andrea Barbagallo

Scusatemi: ho riletto il mio post precedente ed ammetto di essere stato 
estremamente vago. Provero' ad essere piu' chiaro.
Premetto che vorrei realizzare un'applicazione di tipo gestionale per aziende 
(es. fatturazione e magazzino) che sia il piu' possibile indipendente dal tipo 
di database utilizzato per contenere i dati ed il piu' possibile "scalabile". 
Col termine scalabile intendo la possibilita' di poter funzionare sia 
utilizzando un database dBase in monoutenza su un singolo pc, sia utilizzando 
come database Access condiviso in multiutenza da due soli pc messi in rete, sia 
collegandosi ad un server Oracle in uno scenario in cui, con la stessa 
applicazione, centinaia di utenti della stessa rete di pc accedono al medesimo 
database.
Tenendo presente questi obiettivi ideali (che probabilmente non sono 
realizzabili del tutto ma da cui comunque non vorrei discostarmi troppo) mi 
chiedo quali siano le tecniche di programmazione piu' efficaci per gestire il 
problema degli accessi concorrenti di piu' utenti agli stessi dati.
So che spesso la tecnica usata e' quella di impostare un lock fisico sul record 
quando l'utente inizia a modificarne i campi e mantenerlo fino alla pressione 
del tasto "salva". In questo modo, se un altro utente prova contemporaneamente a 
modificare lo stesso record, sul tentativo di impostare un nuovo lock si riceve 
un errore dal database; tale errore viene gestito dal programmatore avvertendo 
il secondo utente che il suo tentativo di modifica verra' annullato perche' i 
dati sono gia' bloccati in scrittura. A me pero' questo approccio non piace per 
i seguenti motivi:
1) viene meno al requisito di indipendenza da uno specifico database (o RDBMS) 
poiche' le tecniche per impostare i lock fisici sui record variano da un 
database all'altro (o sbaglio?);
2) su alcuni tipi di database la gestione dei lock a livello di singolo record 
e' mal gestita o del tutto assente.
Un altro sistema a cui avrei pensato per risolvere il problema e' quello di 
seguito descritto e consiste nel farsi una propria gestione dei lock (lock 
"logici") evitando di loccare fisicamente il record e conservando in una tabella 
l'elenco aggiornato dei record su cui si stanno effettuando delle modifiche.
Ecco i passaggi fondamentali di questa tecnica:
1) Quando l'utente inizia a scrivere sul campo di una maschera di input per 
modificare un record viene, viene effettuato il controllo descritto al punto 2 e 
- in caso di esito positivo - si inserisce un record in un'apposita tabella 
(presente nello stesso db e dedicata esclusivamente alla gestione dei lock 
logici) per segnare che un certo id utente sta bloccando in scrittura un record 
con un certo id presente nella tabella X.
2) La modifica o la cancellazione di un record x vengono consentiti solo se, 
nell'apposita tabella descritta al punto 1, non sono presenti registrazioni 
contenenti l'id del record x. Nel caso in cui almeno una registrazione sia 
presente, dalla stessa tabella viene letto l'id utente corrispondente al lock 
riscontrato e si mostra all'utente un messaggio di errore del tipo "Permesso in 
scrittura negato: l'utente Mario sta bloccando il record corrente".
3) Quando l'utente del punto 1 ha finito di modificare i campi e preme il 
pulsante "Salva", i nuovi dati vengono scritti sul record e si elimina la 
registrazione del lock logico dall'apposita tabella descritta al punto 1.
Tuttavia quest'ultima soluzione dovrebbe essere implementata da zero.
Mi chiedevo quindi se esistessero ulteriori tipi di approcci al problema e 
magari delle tecnologie/tool/librerie gia' pronte per gestire gli accessi 
concorrenti rispettando il piu' possibile gli obiettivi precedentemente enunciati.
Ciao
Andrea Barbagallo

 Andrea Barbagallo
Non ho letto tutto il tuo post, ma ci sono un paio di cose che ho letto 
che mi hanno fatto un po' rabbrividire.
Prima cosa la scelta del database. Nomini Access con accesso multiutenza.
A questo punto, perchè non passare ad un database serio e non una cosa 
che gli assomiglia poco e male? (per favore non lanciate flame. Access 
*non* *è* un database relazionale degno di questo nome. Per non parlare, 
poi, della sicurezza dei dati).
Ci sono diverse soluzioni, free e non, sia in mondo M$ che al di fuori 
di esso.
Se proprio vuoi rimanere in mondo M$, ti consiglio MSDE. Si tratta del 
motore di SQL Server, senza tutti i programmi di contorno. Oppure 
potresti muoverti verso PostgreSql (ottimo) o MySQL (altro db buono).
I vantaggi principali sono
1) avere database seri che ti garantiscono anche che i dati non vanno 
persi per colpa di un accesso contemporaneo al file di DB.
2) (su Postgres ci sono, su MSDE dovrebbero esserci e su MySQL non so) 
puoi impostare vincoli di integrità referenziale tra le tabelle, 
impostare indici per un accesso migliore alle tabelle, gestire trigger 
per effetturare operazioni particolari prima o dopo le query in modo 
automatico (come per esempio mettere in pista un "cestino" o bloccare 
una update se il record è già stato finalizzato)
3) (anche qui non credo che MySQL abbia qualcosa di simile, ma mi posso 
sbagliare) puoi usare delle stored procedure (non so come le chiami 
MSDE), ossia codice che salvato nel database ed eseguito dal database, 
ti permette di automatizzare tutta una serie di operazioni.
4) manutenzione più facile
5) accesso con username e password per la protezione dei dati (puoi 
anche impostare utenti che hanno solo diritti di interrogazione)
6) prestazioni migliori
e tanti altri vantaggi.
In più, MSDE e PostgreSQL (anche MySQL, ma solo con l'ultimo tipo di 
database che hanno aggiunto nella versione 4 o 5) supportano già le 
transazioni, ossia permettono l'accesso simultaneo al database a più 
utenti (e non parlo di solamente 2 utenti) interbloccando 
automaticamente le operazioni di selezione e modifica, solo se queste 
avvengono sugli stessi elementi, e permettendoti di confermare o 
annullare l'intera sequenza di modifiche all'ultimo momento (apri la 
transazione, fai una serie di query, nessun altro può modificarti i dati 
sotto al naso, trovi che esiste una condizione che non ti piace o non 
piace al db, come una foreign key non valida, annulli la transazione e 
nessuna modifica è stata fatta al DB, oppure se non ci sono errori, 
confermi la transazione. Quando la transazione termina, gli altri 
possono accedere a quei record e continuare il loro lavoro come se nulla 
fosse).
Come metodo di accesso, poi, puoi considerare l'uso delle ODBC (un po' 
pesantine, a mio parere, ma ti permettono di astrarti sufficientemente 
dal tipo di database che stai utilizzando).
Ultima cosa, ma non per importanza, un database serio come quelli che ti 
ho elencato, può stare anche su un'altra macchina collegata in rete. 
Access aveva problemi di corruzione del file di dati (non so se questo 
baco sia stato corretto o no) in caso di accessi da rete.
Spero di esserti stato utile.
Luca


Non funzia.
Perche' potrebbero essere contemporaneamente due client a testare '...se 
nell'apposita tabella sono presenti registrazioni contenenti l'id del record 
x...'  e quindi a pensare che il tal record sia disponibile per la scrittura 
e quindi entrare in scrittura su quel record, sbagliando.
Non e' possibile eseguire la trafila:
- vedo se e' disponibile
- se disponibile entro in scrittura
Perche' nel tempo che passa dalla prima operazione alla seconda, qualche 
altro client potrebbe essere entrato in scrittura sullo stesso record.
E per quanto improbabile sia, ti assicuro che se puo' succedere, allora 
succede (prima reg. di Murphy) e se sei sfortunato succede il pomeriggio 
prima della sera che dovevi incassare l'acconto del programma appena 
consegnato (seconda di Murphy), soldi che servivano per fare bella figura e 
portare a cena con la tua nuova morosa (terza di Murphy) .
Se vuoi che non succeda, deve essere impossibile che succeda, ma proprio 
tecnicamente impossibile, bachi di Windows a parte (quarta di Murphy).
L'unico modo che hai di realizzare una concorrenza robusta e' di verificare 
se ti viene restituito un errore quando tenti di scrivere sul record 
(concorrenza ottimistica) e reagire di conseguenza, oppure lockare quel 
record, lavorarci sopra, e s-lockarlo quando hai finito le operazioni 
(concorrenza pessimistica).
Personalmente ti consiglio la prima possibilita', non blocchi nessuno, ti 
permette un'alto livello di concorrenza delle operazioni, anche se devi 
lavorare maggiormente sul  '...reagire di conseguenza...', devi quindi 
prevedere una casistica piu' ampia di possibili risultati al tentativo di 
update e gestirli correttamente, quindi forse un pelino piu' laboriosa da 
implementare ma sicuramente piu' efficace nell'utilizzo reale 
dell'applicazione.
Di piu' nin-tzoo.
Ciao
RobertoA

 Andrea Barbagallo
Middleware?
http://it.wikipedia.org/wiki/Middleware
Ma potrei aver capito male...
Saluti
JJ
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 RobertoA
Ciao anche a te e grazie per i tuoi preziosi consigli... anche da parte della 
mia ragazza :-)
Andrea Barbagallo

 
Una soluzione migliore e' evitare di accedere al database a "basso" livello.
Prova a definire una interfaccia per l'accesso ai tuoi dati ad alto
livello e implementa questa interfaccia per ogni database che vuoi
supportare (usando i meccanismi che ogni database offre).
Portabilita' significa anche questo, non solo scrivere del codice valido
ovunque (che, IMHO, e' una utopia).
E' una faticaccia, non l'ho mai fatto (ma l'ho proposto per lo sviluppo
di Phasis [1] anche se il progetto e' fermo da molto tempo), ma ti da
molti vantaggi, tra cui quello di poter implementare l'interfaccia
tramite RPC ed accedere in maniera trasparente ad un database in rete.
[1] 
http://devel.phasis.it/
    E' scritto in Python, e' in fase di refactoring, ma le definizioni
    (da fare) dello schema per database relazionali e della interfaccia
    di accesso ai dati sono del tutto indipendenti.
    Ad esempio si usa SQL (o diagrammi) per la prima e IDL per la
    seconda, volendo essere pignoli.
Saluti  Manlio Perillo

 della mia ragazza :-)
A dire il vero qualcuno ha sentito parlare anche della quinta di Murphy che 
recita piu' o meno cosi':
""...in caso vengano poste domande sulla concorrenza dei db allora la morosa 
del richiedente dovra' ringraziare 'personalmente' colui la di cui risposta 
verra' ritenuto un prezioso consiglio..."
Bon, ci sentiamo in privato ....
Ciao
RobertoA