Newsgroup: it.comp.software.database
Titolo: sondaggio

salve,
supponendo di dover conteggiare i dati di un sondaggio a cui si risponde
con SI/NO, come posso ovviare al problema che 2+ votanti accedano
contemporaneamente alla tabella e che si perdano 1+ voti?
Se la tabella è questa:
------|-----
   SI     NO
------|-----
   35     21
------|-----
  presumo che 2 votanti possano leggere, per esempio, 35 e che
  poi gli aggiungano 1, perdendo una espressione di voto.
Grazie.

 contemporaneamente alla tabella e che si perdano 1+ voti?
Si locka il DB (o la tabella o la riga).
Non so se una "update tabella set dato=dato+1" sia concurrent-safe in 
tutti i DB.
Bye.

Alessandro Pellizzari ha scritto:

ma quando una occorrenza trova il blocco della tabella, occorre gestire
l'errore oppure se ne occupa lo RDBMS appena la tabella torna libera?
Grazie.

 l'errore oppure se ne occupa lo RDBMS appena la tabella torna libera?
Dipende dalla chiamata che usi. Se gli chiedi di mettersi in attesa, 
aspetta fino all'unlock (o al timeout della connessione), altrimenti ti 
torna subito un errore.
Bye.

Alessandro Pellizzari ha scritto:

ti ringrazio, non mi resta che provare.
Saluti.

  poi gli aggiungano 1, perdendo una espressione di voto.
Ciao
Questo e` il problema detto dei "lost update".
Si ha quando due transazioni lavorano con i valori letti in
origine, ci fanno dei calcoli (diversi o lo stesso[*] calcolo come
in questo caso particolare) e poi li sovrascrivono coi risultati.
Bisogna usare il meccanismo specifico del dbms in questione e
settare l'opportuno livello di isolamento per evitare il problema
in questione.
In particolare e` fondamentale sapere quale sia il livello
applicato dal dbms (per default o per impostazioni particolari).
[*] E' interessante notare come in questo caso, benche' il valore
scritto sia il medesimo (36), questo dato e` comunque errato
secondo la voluta semantica di aggiornamento.
Si puo' sapere "a priori" se tale dato sia errato oppure no
solamente conoscendo la semantica dell'istruzione di aggiornamento,
o meglio, bisogna sapere "cosa intendeva dire" il programmatore.
Ad esempio due transazioni parallele:
T1: Update Sondaggio set no = 36
T2: Update Sondaggio set no = 36
(significato: ci sono stati 36 voti negativi)
...hanno lo stesso effetto dei lost update nell'esempio del
sondaggio, ma ora il risultato e` "corretto" dal punto di vista
della presunta semantica (perlomeno per quanto desumibile dalla
lettura del listato[**]).
Per trasportare il secondo esempio in qualcosa di piu' intuitivo
dei numeri:
T1: UPDATE Presidents SET name = 'Obama' WHERE state = 'USA'
T2: UPDATE Presidents SET name = 'Obama' WHERE state = 'USA'
(significato: il nuovo presidente ora e` Obama)
L'eventuale esecuzione contemporanea delle due transazioni non
cambiera` il significato dell'update, cosi' che la riscrittura
due volte dello stesso valore non viene considerato "errore".
[**] Il che potrebbe non bastare; si consideri l'esempio:
T1: UPDATE Presidents SET name = 'Obama', PresNum = PresNum + 1
T2: UPDATE Presidents SET name = 'Obama', PresNum = PresNum + 1
(significato: il "prossimo" presidente e` Obama)
... ho un caso un po' ambiguo in cui l'esame del listato da solo
potrebbe non bastare. 

 in tutti i DB.
Di per se' non lo e`, almeno secondo la pretesa semantica, ma solo
in  associazione ad un livello di isolamento.
Il motivo e` che qualunque istruzione SQL e` interrompibile
(proviamo ad ipotizzare una tabella di qualche milione di righe) e
sia perche' il comando comporta sia una lettura (dato+1) che una
scrittura (dato=) dalla stessa colonna.
Potrebbe esserlo nel caso di una ipotetica istruzione atomica
INCREMENT(dato).
Da notare che in questo caso posso ottenere il risultato voluto
solo mettendo un lock in lettura (la MVCC da sola non basta). 

 l'errore oppure se ne occupa lo RDBMS appena la tabella torna libera?
Sfatiamo questo mito: trovare un lock non e` assolutamente un errore!
Semplicemente l'operazione viene messa in attesa e riprendera` da sola
appena possibile; questo e` il comportamento "standard" visto che
non specifichi dbms o situazioni particolari.
I lock non sono negativi, sono dei semafori che impediscono di
schiantarsi! 

contemporaneamente alla tabella e che si perdano 1+ voti?
dipende dalla DB che usi, e dalla conseguente sintassi.
con Firebird io uso :
   select ..............  for update with lock

    select ..............  for update with lock
Ciao a tutti e grazie per le delucidazioni.
Per la cronaca, l'rdbms č mysql 5.
Saluti.