Valutazione 4.87/ 5 (100.00%) 5838 voti

Condividi:        

Gestire la concorrenza in ASP

Hai problemi con i file Zip, vuoi formattare l'HD, non sai come funziona FireFox? O magari ti serve proprio quel programmino di cui non ricordi il nome! Ecco il forum dove poter risolvere i tuoi problemi.

Moderatori: Dylan666, hydra, gahan

Gestire la concorrenza in ASP

Postdi Swalke » 06/10/04 15:07

Ciao a tutti!!!
Volevo chiedervi se in asp esiste un modo per garantire l’accesso esclusivo a una variabile o a un database ecc...
Mi spiego meglio: se due utenti scrivono una frase da inserire in fondo a un database e danno contemporaneamente un submit come si fa ad evitare che uno dei due messaggi non venga perso perchè sovrascritto dall’altro?

In un programma java, per cose del genere, basta mettere la funzione che inserisce la frase nel database in un metodo “sinchronized”. In questo caso solo un thread per volta può usare quella funzione e i processi non possono entrare contemporaneamente a lavorare sulla stessa variabile (o tabella del database).
Per chi ne capisce: si evita dunque che i processi entrino contemporaneamente in zona critica.

Bene... ...in ASP come si fa?

Grazie mille!
Avatar utente
Swalke
Hardware Admin
 
Post: 820
Iscritto il: 26/10/01 01:00
Località: Milano

Sponsor
 

Postdi archimede » 06/10/04 17:42

L'accesso esclusivo a una variabile non so cosa sia (quanto meno mi sfugge il concetto in ambito web).

Per quanto riguarda il db, inserire una frase in fondo a un database non ha alcun senso: un db è fatto di tabelle, a loro volta composte da righe, a loro vosta composte da campi.

Immagino che tu ti riferisca alla possibilità di modifica di uno o più campi della stessa riga da parte di due o più utenti contemporaneamente.

Non so come funziona il metodo “sinchronized” di java, ma l'idea di "serializzare" l'accesso ad una risorsa (db, tabella o singola riga che sia) impedendone l'accesso contemporaneo a diversi utenti mi terrorizza.

In ambito web (non client-server, quindi) credo che l'unica soluzione praticabile per evitare di perdere dati in uno scenario come quello sopra descritto sia controllare, prima di fare l'aggiornamento se i dati che sto per modificare non sono stati nel frattempo (cioè da quando li ho richiesti ad ora) cambiati da qualche altro utente. Ergo, mi porto dietro i dati "vecchi" (prima delle modifiche) insieme a quelli nuovi. A questo punto, infine, devo decidere cosa segnalare all'utente (cosa forse meno banale di quanto possa apparire di primo acchito).

Se tutto questo sembra eccessivamente complicato, puoi sempre ignorare questa possibilità (remota?) e lasciare che le modifiche avvengano nell'ordine di arrivo.

HTH.

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Swalke » 06/10/04 20:18

Immagino che tu ti riferisca alla possibilità di modifica di uno o più campi della stessa riga da parte di due o più utenti contemporaneamente.


Si, più precisamente mi riferivo al modificare un record di una tabella di un database.

Non so come funziona il metodo “sinchronized” di java, ma l'idea di "serializzare" l'accesso ad una risorsa (db, tabella o singola riga che sia) impedendone l'accesso contemporaneo a diversi utenti mi terrorizza.


Bhe, siamo messi male perchè tutti i software del mondo devon tutelare le "zone critiche" (porzioni del codice che accedono a variabili condivise) sia nel web che fuori dal web.
I metodi synchronized di java permettono l'accesso al loro codice solo ad un thread per volta (non mi dilungo troppo).



In ambito web (non client-server, quindi) credo che l'unica soluzione praticabile per evitare di perdere dati in uno scenario come quello sopra descritto sia controllare, prima di fare l'aggiornamento se i dati che sto per modificare non sono stati nel frattempo (cioè da quando li ho richiesti ad ora) cambiati da qualche altro utente. Ergo, mi porto dietro i dati "vecchi" (prima delle modifiche) insieme a quelli nuovi. A questo punto, infine, devo decidere cosa segnalare all'utente (cosa forse meno banale di quanto possa apparire di primo acchito).


Ti faccio subito un esempio per farti vedere che non funziona.
Due utenti danno il submit quindi ci sono due processi A e B che vogliono scrivere nella tabella:

Se i processi vengono alternati in questo modo dal server allora si perdono dei dati:
A pesca il dato che deve essere modificato (legge il vlalore x)
B pesca il dato che deve essere modificato (legge il vlalore x)
A vede che è uguale a quello letto
A lo sovrascrive
B vede che è uguale a quello letto
B lo sovrascrive

In questo modo ho perso i dati scritti da A!!! L'alternanza dei processi viene scelta dallo scheduler del server e quindi serve un modo per governarla!

Capito?
Avatar utente
Swalke
Hardware Admin
 
Post: 820
Iscritto il: 26/10/01 01:00
Località: Milano

Postdi pjfry » 06/10/04 20:27

sicuramente si può lockare una tabella anche in asp... però devi progettare bene le cose, se è un processo sul server a fare quei 2 passi si può fare, sicuramente non si può fare se tra un passo e l'altro c'è interazione (lenta) dell'utente
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi archimede » 07/10/04 00:09

Swalke ha scritto:
Non so come funziona il metodo “sinchronized” di java, ma l'idea di "serializzare" l'accesso ad una risorsa (db, tabella o singola riga che sia) impedendone l'accesso contemporaneo a diversi utenti mi terrorizza.


Bhe, siamo messi male perchè tutti i software del mondo devon tutelare le "zone critiche" (porzioni del codice che accedono a variabili condivise) sia nel web che fuori dal web.
I metodi synchronized di java permettono l'accesso al loro codice solo ad un thread per volta (non mi dilungo troppo).
Non è che siamo messi male: l'HTTP è per sua natura un protocollo stateless, per cui risulta problematico e poco efficiente, se non impossibile, mantenere i locks sulle risorse. A seconda del db (tra l'altro, di quale stiamo parlando?) e del linguaggio usato, si dovrà tener conto di ciò per evitare sorprese.
Swalke ha scritto:
In ambito web (non client-server, quindi) credo che l'unica soluzione praticabile per evitare di perdere dati in uno scenario come quello sopra descritto sia controllare, prima di fare l'aggiornamento se i dati che sto per modificare non sono stati nel frattempo (cioè da quando li ho richiesti ad ora) cambiati da qualche altro utente. Ergo, mi porto dietro i dati "vecchi" (prima delle modifiche) insieme a quelli nuovi. A questo punto, infine, devo decidere cosa segnalare all'utente (cosa forse meno banale di quanto possa apparire di primo acchito).


Ti faccio subito un esempio per farti vedere che non funziona.
Due utenti danno il submit quindi ci sono due processi A e B che vogliono scrivere nella tabella:

Se i processi vengono alternati in questo modo dal server allora si perdono dei dati:
A pesca il dato che deve essere modificato (legge il vlalore x)
B pesca il dato che deve essere modificato (legge il vlalore x)
A vede che è uguale a quello letto
A lo sovrascrive
B vede che è uguale a quello letto
B lo sovrascrive

In questo modo ho perso i dati scritti da A!!! L'alternanza dei processi viene scelta dallo scheduler del server e quindi serve un modo per governarla!

Capito?
Tanto per fare un esempio, se io ho una form html per modificare il cognome di un dipendente:
Codice: Seleziona tutto
UPDATE Dipendenti SET Cognome=<nuovo cognome> WHERE Cognome=<VecchioCognome>
direi che dovrebbe servire allo scopo.

HTH.

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Swalke » 07/10/04 00:46

X PJ: sicuramente il lok deve avvenire solo al momento dell' update...
...per intenderci una cosa del tipo
LOK
query di insert
UNLOK
dove LOK e UNLOK sono istruzioni che possono essere svolte da un solo processo per volta... ...come i metodi sinchronized di java.
Ma in ASP non so quali possono essere le mie LOK e UNLOK ...per quello che ne so potrebbe essere anche che la concorrenza per gli oggetti ADO è già garantita in qualche modo dal server IIS (o chi di dovere).
Tu sai come si fa?

Ovvio che non serve e non riesco neanche a immaginare un motivo per cui un'applicazione mantiene un lok intento che un utente guarda la pagina.

****

x Archimede: il dbms è access... ...comunque non ci stiamo intendendo... ...credo che tu non abbia capito bene di cosa parlo... ...o forse io non mi sono spiegato bene.
Se la stringa SQL invece di essere quella che mi hai dato tu è:
INSERT INTO Dipendenti (Cognome) VALUES (<nuovo cognome>) WHERE ID = MAX ID
(...scusa se la sintassi non è corretta ma quello che conta è il succo)
...se questa stringa viene lanciata da due utenti contemporaneamente, lo scheduler del server potrebbe mandare in esecuzione i due processi di update come segue (smembramento della queri in istruzioni di basso livello ipotetiche):

A: seleziona max id (valore estratto = 5) e lo mette in memoria allocata per A
B: seleziona max id (valore estratto = 5) e lo mette in memoria allocata per B
A: scrive cognome dove id=5
B: scrive cognome dove id=5 (e sovrascrive i dati di A)
A: max_id++ (max id diventa 6) nella memoria allocata ad A
A: scrive 6 nella memoria condivisa che contiene il valore di max ID
B: max_id++ (max id resta 6) nella memoria allocata a B
B: scrive 6 nella memoria condivisa che contiene il valore di max ID


...e così perdi i dati di A che vengono sovrascritti da b.
Avatar utente
Swalke
Hardware Admin
 
Post: 820
Iscritto il: 26/10/01 01:00
Località: Milano

Postdi pjfry » 07/10/04 08:54

Swalke ha scritto:Ovvio che non serve e non riesco neanche a immaginare un motivo per cui un'applicazione mantiene un lok intento che un utente guarda la pagina.

per esempio, una pagina di prenotazione di posti al cinema? l'utente la apre e vede 2 posti disponibili, ci pensa, clicca yes e i posti nel frattempo li ha presi un altro... ovviamente non è un problema risolvibile con i lock, ma qualcuno potrebbe pensarci no? :D

purtroppo non avendo mai usato asp non so dirti i comandi, in php c'erano sicuramente lock e unlock
in ogni caso, se usi una query unica come quella del tuo esempio, dovrebbe essere il dbms ad assicurarsi che sia atomica, soprattutto se quell'ID deve autoincrementarsi...
il problema che ti poni dovrebbe essere stato affrontato da chi ha scritto il database... nel caso di access però potrebbe averlo scritto un idiota qualsiasi quindi :roll: :lol:
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi archimede » 07/10/04 08:59

Swalke ha scritto:x Archimede: il dbms è access... ...comunque non ci stiamo intendendo... ...credo che tu non abbia capito bene di cosa parlo... ...o forse io non mi sono spiegato bene.
Se la stringa SQL invece di essere quella che mi hai dato tu è:
INSERT INTO Dipendenti (Cognome) VALUES (<nuovo cognome>) WHERE ID = MAX ID
(...scusa se la sintassi non è corretta ma quello che conta è il succo)
...se questa stringa viene lanciata da due utenti contemporaneamente, lo scheduler del server potrebbe mandare in esecuzione i due processi di update come segue (smembramento della queri in istruzioni di basso livello ipotetiche):

A: seleziona max id (valore estratto = 5) e lo mette in memoria allocata per A
B: seleziona max id (valore estratto = 5) e lo mette in memoria allocata per B
A: scrive cognome dove id=5
B: scrive cognome dove id=5 (e sovrascrive i dati di A)
A: max_id++ (max id diventa 6) nella memoria allocata ad A
A: scrive 6 nella memoria condivisa che contiene il valore di max ID
B: max_id++ (max id resta 6) nella memoria allocata a B
B: scrive 6 nella memoria condivisa che contiene il valore di max ID


...e così perdi i dati di A che vengono sovrascritti da b.
Forse parliamo di due cose diverse: io dei problemi che ci sono nella modifica (UPDATE) di un record esistente, tu forse stai parlando dell'inserimento (INSERT) di un nuovo record. D'altra parte INSERT non supporta la clausola WHERE per cui faccio fatica a seguirti. Ancora una volta, non so cosa sia la memoria condivisa (un dato nel db, una variabile Application(), ...?) e comunque non mi pare riguardi direttamente il problema (locking sul db e concorrenza in ambito Internet/multiutente).

Di cosa parlo io? Degli update persi. Scenario:

T0: l'utente A seleziona i dati del record 1 ed inizia a modificarli
T1: l'utente B seleziona i dati del record 1 (vede le stesse informazioni che A vedeva inizialmente) ed inizia a modificarli
T2: l'utente A invia le proprie modifiche (che vengono correttamente registrate)
T3: l'utente A verifica che le proprie modifiche siano state correttamente registrate e va a casa
T4: l'utente B invia le proprie modifiche (che vengono correttamente registrate)

Se in T4 non c'è nessun controllo che i dati del record sono cambiati dopo T1 l'utente A avrà di che lamentersi.

Per risolvere tale problema (che, come vedi, non implica necessariamente che le operazioni avvengano esattamente nello stesso momento) devi usare un tipo di locking:

1) pessimistico: prima di inviare i dati da modificare sulla form dell'utente, seleziono e blocco in qualche modo il recordo in modo che non sia modificabile da altri
2) ottimistico: in fase di update mi porto dietro i valori originali di tutti i campi da aggiornare e faccio la modifica solo se i valori attualmente presenti nel db sono uguali ai miei valori originali (UPDATE Dipendenti SET Cognome=<nuovo cognome> WHERE ID = DIP_ID AND Cognome=<VecchioCognome>)

In un'applicazione Web credo che solo l'opzione 2 (o qualcosa di analogo) sia ragionevolmente implementabile.

Non so se mi sono spiegato.

Alessandro

PS: se sei in procinto di scrivere un'applicazione seria per il Web (come la tua domanda lascia supporre) forse dovresti anche pensare ad un db altrettanto serio. Per evitare polemiche, apprezzo Access (anche se c'è chi pensa che non sia un vero RDBMS) ma in ambiente multiuser con elevata concorrenzialità lo considero un po' deboluccio.
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Dylan666 » 07/10/04 10:54

Domanda da perfetto ingorante: ma non parlate forse del metodo "Application.Lock"? :roll:

http://www.morpheusweb.it/html/manuali/ ... cation.asp
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi archimede » 07/10/04 11:10

Dylan666 ha scritto:Domanda da perfetto ingorante: ma non parlate forse del metodo "Application.Lock"? :roll:
No (non io, almeno ;)): io intendo lock sui records del db.

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Dylan666 » 07/10/04 11:16

Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi archimede » 07/10/04 11:40

Beccato! Questo è un altro approccio: segnare i records come locked prima delle modifiche (al momento della SELECT).
This code runs when the page is first opened, it checks the value of the field Locked for this record. If the value is Yes, that indicates that this record is already being edited and will redirect the user to the locked.asp page, passing through a parameter to further identify the record.

If the value is anything other than Yes, then the call to the procedure will be made to lock this record. Once done, it will continue to display the record on screen for the user safe in the knowledge that no-one else will be able to view the record whilst they are working on it.
Ha il vantaggio che l'utente viene bloccato prima di fare le modifiche, però... Il problema principale è, secondo me, che si corre il rischio di passare ore a fare unlock (perchè l'utente è andato a pranzo, ha chiuso il browser, spento il PC, ecc.):
this is one way of a few I can think of, certainly not foolproof, you could build on this example by using the LockDate and LockTime fields to check if it is older than a certain amount of time say 10 minutes and then automatically, unlock the record.
La parte che non mi è chiara è "automatically": come si fa ad automatizzare tale controllo (soprattutto in Access)?

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi pjfry » 07/10/04 11:46

archimede ha scritto:La parte che non mi è chiara è "automatically": come si fa ad automatizzare tale controllo (soprattutto in Access)?

dovrai gestirtelo a mano con dei processi schedulati sul server immagino, no?
cmq è proprio l'esempio di interazione lenta dell'utente di cui parlavo sopra e che mi pare decisamente impraticabile... ovviamente dipende sempre dai contenuti del db, potrà anche esserci qualche caso in cui funziona :roll:
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi Dylan666 » 07/10/04 11:54

Codice: Seleziona tutto
you could build on this example by using the LockDate and LockTime fields to check if it is older than a certain amount of time say 10 minutes and then automatically, unlock the record.


Più che a livello di server penso a livello di script, cioè usare il campo "LockTime" per prendere il tempo su un timer di 10 minuti che poi sblocchi il record.
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi archimede » 07/10/04 11:58

pjfry ha scritto:
archimede ha scritto:La parte che non mi è chiara è "automatically": come si fa ad automatizzare tale controllo (soprattutto in Access)?

dovrai gestirtelo a mano con dei processi schedulati sul server immagino, no?
Direi di si (a meno che non ne vuoi fare il tuo lavoro a tempo pieno): Oracle ha dei propri job che puoi periodicamente (ed automaticamente) eseguire, altri db (tipo SQLServer) immagino pure, ma Access? Devi allora farlo a livello di SO, ma qui entriamo in un ambito in cui non ho esperienza (e comunque siamo al di fuori di ASP).
pjfry ha scritto:ovviamente dipende sempre dai contenuti del db, potrà anche esserci qualche caso in cui funziona :roll:
Ovviamente.

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi archimede » 07/10/04 11:59

Dylan666 ha scritto:
Codice: Seleziona tutto
you could build on this example by using the LockDate and LockTime fields to check if it is older than a certain amount of time say 10 minutes and then automatically, unlock the record.


Più che a livello di server penso a livello di script, cioè usare il campo "LockTime" per prendere il tempo su un timer di 10 minuti che poi sblocchi il record.
Questa non l'ho capita: puoi fare un esempio?

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Dylan666 » 07/10/04 12:14

Mettiamo caso che un secondo utente apra la pagina ma l'altro sia aconra a pranzo bloccando il record da 60 minuti. Non si può sbloccare il database al massimo dopo 10 minuti dall'inizio di una nuova richiesta di accesso al record in modo da non poter far star ogni utente più di 10 minuti col lock attivo?

Cioè fargli scadere la sessione insomma?
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi archimede » 07/10/04 12:21

Dylan666 ha scritto:Non si può sbloccare il database al massimo dopo 10 minuti dall'inizio di una nuova richiesta di accesso al record in modo da non poter far star ogni utente più di 10 minuti col lock attivo?
Intanto non si tratta di un "lock attivo" (qualsiasi cosa tu intenda con questo termine): viene fisicamente modificato il record sul db inserendo le informazioni relative all'ultima richiesta di modifica. Il nodo è proprio lo "sblocco" (cioè resettare il record togliendo tali informazioni, che bloccano gli altri utenti): chi, come e quando lo fa?

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi archimede » 07/10/04 12:25

Forse ho capito: tu intendi sbloccare il record se, al momento della seconda richiesta, risulta che il lock è lì da più di x minuti.

Può essere una possibilità, un po' funambolesca forse, ma fattibile...

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Dylan666 » 07/10/04 12:26

Utente 1 = connesso da 60 minuti alla pagina non ancora inviata

Utente 2 = appena connesso.

Nella pagina di Utente 2 c'è scritto: se Utente 1 ha il lock >10 minuti ALLORA Utente 1 unlock e Utente 2 lock.

Insomma, è possibile subordinare il lock a un fattore tempo e toglierlo dalle pagina di altri accessi?
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Prossimo

Torna a Software Windows


Topic correlati a "Gestire la concorrenza in ASP":


Chi c’è in linea

Visitano il forum: Nessuno e 9 ospiti