Newsgroup: it.comp.software.database
Titolo: locks di postgresql

ciao vorrei sapere se esiste la possbilità di bloccare un record anche in
lettura senza ricorrere al blocco di tutta la tabella con EXCLUSIVE.
In pratica ho n record disponibili e vorrei evitare che la select di un
altro utente visualizzi il record utilizzato dal primo utente prima che
questo lo abbia aggiornato.
Un saluto e grazie!


Dai un occhiata al costrutto SELECT ... FOR UPDATE nella documentazione.
Non l'ho mai usato nello specifico ma dovrebbe essere quello che ti serve.
Martino.
-- 
Quando avrete abbattuto l'ultimo albero, quando avrete pescato l'ultimo
pesce, quando avrete inquinato l'ultimo fiume, allora vi accorgerete che
non si puo' mangiare il denaro.  Proverbio Indiano

 questo lo abbia aggiornato.
se il primo utente fa le sue operazioni all'interno di un blocco 
transazionale (i.e. BEGIN/COMMIT) il secondo vedrà solo la before image 
finchè tutto il blocco di istruzione del primo utente non è finito. Non 
c'e' bisogno di loccare nulla per questo...
-- 
Fabrizio "Hermooz" Ermini

H> se il primo utente fa le sue operazioni all'interno di un blocco
H> transazionale (i.e. BEGIN/COMMIT) il secondo vedrà solo la before
H> image finchè tutto il blocco di istruzione del primo utente non
H> è finito. Non c'e' bisogno di loccare nulla per questo...
Ciao Fabrizio,
sto iniziando a smanettare un po con PostgreSQL e mi
chiedevo se e' possibile in qualche modo forzare il lock
per impedire alla seconda transazione di effettuare la
lettura della before image.
Ciao e grazie,
--
Gianluca Hotz - SQL Server MVP
http://italy.mvps.org
 - 
http://www.ghotz.com
http://www.ugiss.org
  - 
http://www.ugidotnet.org

 lettura della before image.
se la seconda transazione è solo di lettura, è sbagliato bloccarla: il 
comportamento corretto è fare vedere l'ultima versione valida dei dati. 
Se anche la seconda transazione pero' ha la possibilità di modificarli, 
è possibile gestire un lock con la già citata "select for update": in 
tal caso ogni successiva query che puo' modificare gli stessi record 
viene ritardata fino alla conclusione delle precedenti. Attenzione ai 
deadlock... :-)
-- 
Fabrizio "Hermooz" Ermini


ho n scede cliente che le operatrici (una trentina) devono chiamare una sola
volta. Perciò ogni operatrice accede alla prima scheda "vergine"
disponibile, la marca come occupata nel campo bloc, chiama il cliente e in
seguito l'aggiorna con il risultato della chiamata.
select -> prima scheda libera
update bloc = occupata
..telefonata
update esito = esito della chiamata
Con mysql mi ritrovavo nella situazione in cui piu operatrici accedevano
alla stessa scheda con chiare conseguenze negative..
Ho risolto con il LOCK TABLES che comunque fa perdere tempo perchè le query
concorrenti devono aspettare il loro turno.
Speravo che postgres avesse questo famigerato lock della singola riga
(lettura e scrittura) in caso di successo della select.

update esito = esito della chiamata
Non conoscendo comunque l'implementazione, ma perche' non metti un
attributo booleano su cui esegui la transazione?
-- 
Linux Registered User #181013
[Exokernels] Although one approach to eliminating bloated, buggy,
unreliable operating systems is to make them smaller, a more radical
one is to eliminate the operating system altogether.

 
Aaaargh!
Ma che row locking o table locking, la cosa va gestita a livello di 
progetto di schema!
Dividi gli attributi della scheda in attributi a sola lettura e 
attributi "aggiornabili",ovvero i dati di una telefonata, e mettili in 
due tabelle diverse. Gli attributi in sola lettura (dati anagrafici 
ecc.) li usi come master e i record aggiornabili come detail.
Per ogni telefonata l'operatore puň vedere i dati di tutte le chiamate 
precedenti, ma non di un'eventuale chiamata in corso non ancora 
conclusa, com'e' giusto. Se ci sono due chiamate in contemporanea, 
ognuna viene collegata alla giusta scheda senza conflitti, deadlock, o 
attese...
bye!
-- 
Fabrizio "Hermooz" Ermini

 attese...
IL problema non sta nell'aggiornare i dati dopo la chiamata ma nel primo
passaggio cioè assegnare a 30 richieste contemporanee 30 schede nuove
diverse!
Nel caso ritieni che non abbia capito il tuo metodo puoi farmi l'esempio di
select iniziale e blocco della scheda?
Grazie ancora

 
E' il concetto di base che non afferro. Perchč parli di "nuova scheda 
disponibile"?
E' un sistema di ticketing?
Sono sicuro al 90% che i problemi che hai nascono dal fatto che la 
struttura del DB non č modellizzata in modo ottimo. Pero' ancora non ho 
capito bene qual'e' il mestiere che deve fare questo DB...


 
Immagino che sia costruito in questo modo: le schede sono già presenti 
nel DB. A lui interessa gestire che un operatore non si ritrovi in 
lavorazione una scheda che in realtà è già stata presa da un altro 
operatore.
Per me potresti aggiungere un campo nella scheda che ti dà lo stato 
della scheda esempio (0 da lavorare, 1 in lavorazione, 2 lavorata) e 
quando un operatore prende in carico la scheda fai subito una bella 
update dello stato.


 
Yep, che questo sia quello che vuole fare lui l'ho capito, ma cosa 
rappresentano queste "schede"? Perchè che ne sono N pregenerate e sono 
monouso? E' questo che non afferro...
-- 
Fabrizio "Hermooz" Ermini


scusate forse sono stato poco chiaro e puo essere un discussione utile a
molti.
Cerco di semplificare al massimo la procedura con un esempio di gioco
(php-mysql):
Ho una tabella "gioco" con un solo record e 30 amici davanti al proprio pc.
Il record ha questi campi:
id     bloc    //campi
1       N      //valori
Il record puo e deve essere visualizzato e aggiornato da un solo giocatore.
La sfida è aprirlo prima di tutti gli altri!
Come si fa?
1 - SELECT id,bloc FROM gioco WHERE bloc='N' LIMIT 1
//cerco il primo record disponibile con bloc=N
se lo trovo:
2 - UPDATE gioco SET bloc='C' WHERE id=x
a questo punto il record non sarà piu disponibile per nessuna select e un
solo giocatore avrà visualizzato la scheda!
Il punto critico è il tempo che intercorre tra il passaggio 1 e 2. Infatti è
in questa frazione di secondo che gli altri giocatori hanno ancora accesso
al record
Risultato: è possibile che più giocatori blocchino in sequenza la stessa
scheda
Vi assicuro che nonostante la proverbiale velocità di mysql bastano 30
connessione simultanee per creare una situazione di questo tipo.
Siccome è un modo di lavorare abbastanza normale in un callcenter mi
chiedevo se esistesse un procedura più snella del LOCK TABLES di mysql in
postgresql.
Un saluto e grazie!