Newsgroup: it.comp.www.php
Titolo: Concorrenza con PostgreSQL

Salve.
Stò sviluppando un piccolo sito in PHP utilizzando il database postgres.
Mi ritrovo a risolvere questo problema : Ho bisogno di gestire la
concorrenza nell'accesso e nell'aggiornamento
di una tabella (o meglio ancora di un singolo record).
E' necessario che UNO e soltanto UNO utente alla volta sia in grado di
accedere e modificare il dato e inoltre che
quando un utente abbandona il dato facendo 'commit' (???) il dato sia stato
effettivamente modificato... il mio dubbio riguarda
la possibilità che il motore di postgres 'metta in coda' la richiesta di
update e un eventuale utente successivo vada a leggere il dato
non ancora modificato.
Quindi :
- Quale tecnica mi conviene utilizzare per raggiungere questo risultato ?
- Come faccio ad essere sicuro che il database abbia 'VERAMENTE' aggiornato
il risultato anche per gli altri utenti del sito?
- Esistono soluzioni efficienti che non sono legate al database utilizzato
(vedi : porting su MySql)  ?
- Esistono soluzioni efficienti che non sono legate al sistema operativo
(vedi : porting su Apache sotto Windows)  ?
Ciao e grazie!

(vedi : porting su Apache sotto Windows)  ?
DB è una cosa, Web è un'altra.
ciao
--
Nella vita, come in tram, quando ti siedi e' il capolinea.
--
Michel <ZioBudda> Morelli               
mic...@ziobudda.net
ICQ UIN: 58351764                       PR of Linux in Italy
http://www.ziobudda.net
 
http://www.phpdev.it

 ha scritto nel messaggio
news:_%Wx9.120335$RO.30...@twister1.libero.it...

Con MySql, quando voglio essere sicuro che uno solo metta le mani su di una
riga della tabella,
nella tabella metto un campo con un identificatore univoco.
Creo una seconda tabella con 3 campi di cui uno è il campo univoco della
tabella prima, il secondo è l'identificativo di chi modifica, il terzo è un
timestamp di quando si è inserito il record.
Creo un indice unique sul primo campo.
Quando un utente deve modificare una riga, il sorgente php, deve fare le
seguenti cose:
Cancellare dalla seconda tabella tutte le righe più vecchie di X minuti.
Inserire nella seconda tabella una riga con: codice univoco della riga da
modificare, nome utente, now().
Se la query ha avuto successo, posso mostrare la finestra di editing della
riga.
Se la query non ha avuto successo (riga doppia) qualcun'altro sta
modificando la riga, mostro una finestra che informa che la riga è già in
editing.
Finita la fase di edit. per registrare le modifiche, controllo che sia
ancora valida la mia riga di "prenotazione" inserita nella seconda tabella.
Se è ancora valida modifico la prima  tabella altrimenti mostro finestra di
tempo scaduto.
Quando lascio la finestra di editing, levo dalla seconda tabella  la riga di
prenotazione di chi stava modificando.
Se  l'utente che sta modificando si addormenta davanti al PC, dopo X minuti
la sua riga della seconda tabella scade e verrà cancellata dal prossimo che
vuole modficare la riga.
Al suo risveglio, dopo un numero maggiore di X di minuti, pur essendo nella
finestra di edit, quando conferma l'edit, non riuscirà a modificare perchè
la sua riga è scaduta e forse anche cancellata.
Anche se il processo di editing viene interrotto, dopo X minuti il record
risulterà libero.
La fase di editing, può interessare più pagine di form, in questo caso, ogni
volta che accedo ad una pagina o faccio un refresh, aggiorno il timestamp
della seconda tabella così l'utente ha ancora X minuti per terminare la sua
modifica.
--
Cordialmente.
Carmelo Carchedi
Il mio e-mail non ha numeri,
ricordati di toglierli per rispondere privatamente.
Juniorbit Sas
www.juniorbit.it

 il risultato anche per gli altri utenti del sito?
Se l'utente ha effettuato il commit e l'istruzione non ha riportato errori i
dati sono sicuramente aggiornati.
Se non ricordo male Pg ha la possibilita' di specificare la clausa FOR
UPDATE WITH LOCK nella SELECT
Questo ti permette di leggere i dati ed essere sicuro che nessuno li potra'
leggere finche tu non li abbia modificati ed abbia effettuato il COMMIT o il
ROLLBACK della transazione.
Bella cosa, ma puo' anche crearti dei problemi perche' il secondo utente
rimane bloccato ad aspettare finche' il record non si sblocca o fino a che
scade il timeout.
Pg non ha la possibilita' di dare FOR UPDATE WITH LOCK NOWAIT come per
esempio Oracle. In questa maniera il secondo utente trova il record
bloccato, la SELECT restituisce un errore e tu lo puoi gestire.
Il FOR UPDATE non funziona su tutti i DB. Alcuni ti permettono di scriverlo
nella select ma poi lo ignorano in esecuzione.
Il metodo che uso io per gestire questi casi ed avere una certa uniformita'
di funzionamento su diversi DB e' aggiungere un campo (Es. BLK) ad ogni
tabella e fare un UPDATE su quel campo ogni volta che voglio bloccarlo.
L'update da accesso esclusivo alla riga cosi' un secondo utente che prova a
fare la stessa operazione deve attendere fino a che tu non decidi di
confermare (PostGreSql) oppure gli viene ritornato un errore (Oracle)
Personalmente mi trovo molto bene con FireBird perche' ha una opzione a
livello di connessione che puo' essere impostata a NOWAIT in modo che tu non
debba attendere indefinitivamente ed e' free.
Ciao
--
Andrea Chiadò Piat
Bit Informatica s.r.l.
Progettazione e Sviluppo