Newsgroup: it.comp.appl.access
Titolo: Campi autoincrementanti self made e rischio di duplicazione

Salve,
nel caso che si volesse  gestire il comportamento di un campo
autoincrementante (e.g. un numero di protocollo che ripartisse da 1 al
termine di un periodo di esercizio), una delle opzioni più proposte è
riassunta dal seguente codice:
 
dim Protocollo as  Integer
Protocollo  = Nz(DMax("[NomeCampoProtocollo]","[NomeTabella]"),0)+1
 
Ora, in questo modo , anche se il comando di inserimento del record
venisse impartito  immediatamente dopo la generazione del nuovo
protocollo, in caso di concorrenza ( da intendersi come più utenti
che facciano contestualmente dataentry sulla stessa tabella) iyho non
sussisterebbe il rischio che siano generati codici duplicati?
 
Se così fosse,  generando  il nuovo protocollo all’interno  dello
statement sql  di seguito descritto, sempre iyho si potrebbe evitarne
la duplicazione?
 
INSERT INTO NomeTabella (NomeCampoProtocollo) SELECT max(NomeTabella.
[NomeCampoProtocollo])+1 AS NomeCampoProtocollo FROM NomeTabella;
 
TIA per le risposte.
 
Un salutone,
Stolcius AKA Michele Collatina

 [NomeCampoProtocollo])+1 AS NomeCampoProtocollo FROM NomeTabella;
 
yes (dovrebbe), ioao.
-- 
 
ac (x=y-1)


wrote:

Tnx :-)
 
Stolcius

"Stolcius Von Stolcenberg"  ha scritto nel messaggio 
news:d64f77ad-12c9-4d4d...@m19g2000yqh.googlegroups.com...

_______________Risposta:
Salva il record subito dopo aver generato il numero di protocollo
MA
 
 
 
 

 Salva il record subito dopo aver generato il numero di protocollo
 
Ciao.
anche salvando subito dopo aver generato il numero di protocollo, il
rischio di duplicazione permane e, a un dipresso, dovrebbe essere
proporzionale al volume di concorrenza.
 
Mi spiego meglio con un caso limite.
Utenti A e B.
 
tempo 1     :    l'appl. di A evince il  max(numero di protocollo) -
e.g. 0001
tempo 1, 2 :    l'appl. di A  incrementa il prot. max ricavando 0002
tempo 1,5  :    B evince il  max(numero di protocollo) - lo stesso di
A(0001), in quanto l'applicazione di quest'ultimo non ha ancora
                       effettuato l'insert del nuovo protocollo(0002)
Tempo 1,7 :    A effettua l'insert del prot. 0002
tempo 1, 9 :    l'appl. di B  incrementa il prot. max ricavando 0002
tempo   2   :    B effettua l'insert del prot. 0002 con violazione di
chiave!
 
Be', in effetti, gestendo l'errore forse(la mia è una domanda) si
potrebbe ricavare un workaround che permetta di generare la chiave
successiva in modo puntuale; magari inserendo un error handler che in
caso di violazione di chiave incrementi il protocollo e operi un
resume secco.
 
Così, anche in caso di concorrenza "spietata", il protocollo,
incremento dopo incremento, risalirebbe la china fino a trovare un id
senza il cappello sopra!
 
Ho implementato un POC di questa soluzione e sembrerebbe funzionare.
Però non sono sicuro al cient'pe'cient' che non vi sia qualche
inciampo di cui tener conto.
 
Che ne pensi/pensate?
 
Un salutone,
Stolcius
 
 
 
 
 
 

 Salva il record subito dopo aver generato il numero di protocollo
 
Ciao.
anche salvando subito dopo aver generato il numero di protocollo, il
rischio di duplicazione permane e, a un dipresso, dovrebbe essere
proporzionale al volume di concorrenza.
 
Mi spiego meglio con un caso limite.
Utenti A e B.
 
tempo 1     :    l'appl. di A evince il  max(numero di protocollo) -
e.g. 0001
tempo 1, 2 :    l'appl. di A  incrementa il prot. max ricavando 0002
tempo 1,5  :    B evince il  max(numero di protocollo) - lo stesso di
A(0001), in quanto l'applicazione di quest'ultimo non ha ancora
                       effettuato l'insert del nuovo protocollo(0002)
Tempo 1,7 :    A effettua l'insert del prot. 0002
tempo 1, 9 :    l'appl. di B  incrementa il prot. max ricavando 0002
tempo   2   :    B effettua l'insert del prot. 0002 con violazione di
chiave!
 
Be', in effetti, gestendo l'errore forse(la mia č una domanda) si
potrebbe ricavare un workaround che permetta di generare la chiave
successiva in modo puntuale; magari inserendo un error handler che in
caso di violazione di chiave incrementi il protocollo e operi un
resume secco.
 
Cosě, anche in caso di concorrenza "spietata", il protocollo,
incremento dopo incremento, risalirebbe la china fino a trovare un id
senza il cappello sopra!
 
Ho implementato un POC di questa soluzione e sembrerebbe funzionare.
Perň non sono sicuro al cient'pe'cient' che non vi sia qualche
inciampo di cui tener conto.
 
Che ne pensi/pensate?
 
Un salutone,
Stolcius
 
____________Risposta:
Probabile che non sia stato chiaro.
Tu salvi il record dopo esserti preso il max.
A quel punto chi salva dopo č sicuro di avere un codice univoco
MA
 
 
 
 
 
 
 


E' esattamente quello che fa con la istruzione da lui proposta (1' post).
Tu spezzi in due il problema e quel nanosecondo fra una fase e l'altra 
(se non c'e' transazione) potrebbe essere mortale perche' succede quello 
che l'OP ha descritto. La istruzione da lui proposta fa il tutto nella 
esecuzione della insert e credo che cio' assicuri l'isolamento.
 
 
-- 
 
ac (x=y-1)

 MA
 
Qua siamo all'atomicità........
2 scenari: form associate e non associate
Se la form è associata e il campo è autoincrementale Access si
preoccupa di farti avere l'Id univodo APPENA comincia il nuovo record
(a differenza di altri motori di db). Chiaro che lo puoi fare anche tu
(if NewRecord then....)
Se la form è non associata tutta quella pappardella sui tempi perde di
significato perchè: apro la mia form di inserimento, la compilo,
prendo il caffè, faccio un giro in città e gioco pure al videopocker.
Poi torno, premi INSERISCI, e, solo in questo momento, trovo il max e
faccio l'INSERT
Io personalmente lavoro sempre così (mie comodità) e ti assicuro che
la concorrenza del mio applicativo è elevata (si tratta di vendite
alle casse, quindi molti clienti alla volta tutti su un'unica
tabella). Mai avuto problemi. Chiaro che gli errori eventuali li devi
intercettare.......

 intercettare.......
 
Ciao.
Ho fatto un paio di calcoli e penso che a livello pratico hai
decisamente ragione.
 
Per amor di semplicità, ammettiamo che i nostri poveri utenti facciano
dataentry in una finestra temporale di un'ora.
Postuliamo altresì che l'aggiornamento cubi un millisecondo.
 
Abbiamo quindi 3,6 milioni di possibili istanti in cui un record può
essere aggiornato.
Con 2 soli utenti, la possibilità di collisione per ogni immissione è
dell'ordine di una su... Dieci bilioni!!
6000 volte più bassa di un 6 al superenalotto!
 
Pertanto, anche una ben più ubertosa concorrenza non riuscirebbe a far
travalicare il fenomeno oltre il crinale del raro.
 
Però - c'è sempre un pietoso però - ti ricordo che esiste sempre un
utente che riesce a estrarre dal cappello quell'unica possibilità
negativa; anche se per farlo dovesse annichilire le leggi della fisica
e produrre fenomeni paranormali!
 
E sì, anche noi abbiamo le nostre infallibili leggi di
Murphy...   :-))))
 
Io per non saper nè leggere nè scrivere, una gestioncina dell'errore
ce la infilerei...
 
Un salutone,
 
Stolcius