Newsgroup: it.lavoro.informatica
Titolo: Errore overflow alla stazione ferroviaria

 
ha sbagliato il programmatore ?
 
 
https://ibb.co/Wff1x1R
 
 
ciao

 
https://ibb.co/Wff1x1R
 
 
Non si sa. Bisognerebbe capire per qual motivo si sia verificata una roba del genere.


passi l'errore - nel senso che sicuramente nessuno ha scritto uno 
straccio di integration/acceptance/unit test per quel pezzo di codice - 
ma un'exception del genere non deve rimbalzare cosi' in alto tanto che 
lo stack trace sia visible dall'utente finale
 
li ci starebbe bene una pagina d'errore, anche una generica 500 Internal 
Server Error
 
lo stack trace deve finire nel log su filesystem


hanno lasciato attiva una modalità sviluppo in produzione, cosa ovviamente 
da cialtroni impuniti. ma succede in gran parte dei siti iis e 
asp.net
 
quindi deve essere un qualcosa di congenito di chi lavora su quella 
piattforma.

 piattforma.
 
Ni. Ossia: ovvio, quell'errore non deve in ogni caso essere visibile, ed è vero quel che dice MC.
Tuttavia, mi lascia MOLTO perplesso quel valore. I casi sono due - e penso sarebbero sfuggiti a test automatizzati, a meno di non prevedere esplicitamente la condizione di overflow:
1) si tratta di un ID di qualche oggetto (a rivedere bene, la cosa per cui propendo); se è così, allora è palesemente un errore di progetto, o una svista, perché NESSUNO che usi un database relazionale utilizzerebbe un ID incrementale di tipo int (*);
2) si tratta di un valore di qualche altro genere, nel qual caso sarebbe necessario capire per quale motivo la cosa si sia generata; potrebbe insomma trattarsi di una condizione imprevista e nemmeno ipotizzabile in fase di sviluppo (e mi è accaduto).
 
Noto peraltro che viene usato il .NET framework 4.0. Da quanto gira, senza revisione, quella roba?
 
(*) Sì, lo so. Io sono della scuola di pensiero che afferma: 'gli ID incrementali, in un DB relazionale, non dovrebbero MAI essere usati'; tuttavia, ne viene fatto largo uso e non sono in effetti così scomodi.
 
-- 
Ciao!
Luca

 Sì, lo so. Io sono della scuola di pensiero che afferma: 'gli ID incrementali, in un DB relazionale, non dovrebbero MAI essere usati'; tuttavia, ne viene fatto largo uso e non sono in effetti così scomodi.
 
+1
questo meriterebbe un thread tutto suo. Io evito le sequence come la 
peste e mi tocca evangelizzare altri sviluppatori che per qualche motivo 
ne sono ancora legati (tradizioni dure a morire), ma aimé ci sono i casi 
in cui servono.

 
 
i miei due cent:
 
dato che stando a MS si ha:
 
Data Type Ranges | Microsoft Docs
https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-170
 
 
Type Name 	Bytes 	Other Names 	Range of Values
int 	4 	signed 	-2,147,483,648 to 2,147,483,647
 
e il numero colpevole dell'errore comincia con 22001 suppongo che sia 
composto da anno (due cifre, 22) e giorno dell'anno (tre cifre, 001, primo 
di gennaio)
 
I test fatti anni e anni fa non erano andati cosě avanti da fare le prove 
anche per il 2022 e seguenti :)
 
-- 
/-\ /\/\ /\/\ /-\ /\/\ /\/\ /-\ T /-\
-=- -=- -=- -=- -=- -=- -=- -=- - -=-
........... [ al lavoro ] ...........

Il 03/01/22 00:37, Luca Menegotto ha scritto:

Mi spiace ma sugli id non sono d'accordo
 
 
Se non si usa gli id per le relazioni occorre duplicare i valori delle pk
 
Se hai una pk composta da N colonne occorre duplicarle
E per modificare i valori di una pk occorre seguire le relazioni,molto 
scomodo
Mica per altro oracle ha le sequence ed altri db hanno un metodo simile
Gli id invece le uso ed intensamente e con buon risultati
 
 
 
 
-- 
|___|

 
 
Potrebbe forse essere un'istanza di questo bug, rilevato proprio l'1/1:
 
https://twitter.com/doublehelix/status/1477232476166795267
 
 
-- 
Ciò che si vede, è.
 

 Se non si usa gli id per le relazioni occorre duplicare i valori delle pk 
 
Che, la vecchia teoria relazionale afferma, è solo un bene, perché 
a) sono la minima quantità di dati che è necessario duplicare e 
b) sono automaticamente consistenti.
 
Ripeto, uso anch'io tantissimo sequence e id. Comodi, ma meno chiari.

 di gennaio) 
 
Complimenti, non ci avevo fatto caso. No, secondo me 162556 è un orario; magari 00 è l'id di settimana?
Comunque, a questo punto sì, è colpa del programmatore... 
 
:-D

 Ripeto, uso anch'io tantissimo sequence e id. Comodi, ma meno chiari.
 
per me le chiavi composite sono sempre state il male. lo pensavo prima 
quando si progettava database first, a maggior ragione con gli orm e la 
progettazione code first.
 
qualche anno fa lavoravo su un progetto in ambito bancario. c'era un 
entità che era referenziata da mezzo database. un bel giorno arriva la 
richiesta di una modifica che prevedeva l'aggiunta di un campo che rendeva 
l'attuale chiave non più univoca: è stato un bagno di sangue. se la chiave 
fosse stata un semplice id e il gruppo di campi una semplice unique 
constraint la modifica sarebbe stata questione di un quarto d'ora.
 
ricordo anche negli anni 90 quando lavoravo su un gestionale, c'era il "db 
architect" che si masturbava su queste relazioni che secondo lui 
disegnavano una coerenza perfetta e inattaccabile. c'erano tabelle many-
to-many con chiavi di 7 o 8 campi, con i programmatori che moccolavano 
come turchi per popolarli. follia pura.
 
 

 come turchi per popolarli
 
ma soprattutto popolarli correttamente, impedendo agli utenti di inserire 
bojate


 
 
22 00 16 25 56
 
anche io ho pensato all'orario, ma poi mancherebbe un dato (il giorno della 
settimana) a cui fare riferimento
 
probabilmente c'č piů di un errore ;)


 tuttavia, ne viene fatto largo uso e non sono in effetti così scomodi.
 
va beh, l'alternativa giusta secondo questa scuola di pensiero?

 inserire bojate
 
ma poi ricordo che, al crescere dei dati, venivano fuori continuamente 
problemi di costruzione indici. cioè a seconda della tabella in relazione 
conveniva un indice con un ordine di campi diverso... semplici join fra 
tabelle che degradavano a turno di prestazioni, aggiustavi da una parte e 
rompevi dall'altra... giornate e giornate a cercare una quadra 
impossibile... 


ste cose succedono pure adesso
non è che grazie al "cloud" magicamente le primary key e gli indici si 
creano per magia e sono subito ottimizzati
 
oggi si progetta (o almeno si tenta di progettare) l'ambaradan il più 
possibile asincrono, cosa che a volte nasconde - almeno all'inizio - i 
difetti progettuali del layer di persistence
 
qualcuno di voi ricorderà il caso di Justin Bieber che ha mandato in 
crash Instagram (mi ricordo qualcosa anche con Twitter)


non so quale sia l'opinione di Luca, questa è la mia esperienza:
a meno che il fatto di essere un valore incrementale non abbia senso nel 
dominio dell'applicazione (o ci siano vincoli legali(*)), un valore 
random è la miglior cosa, esempio il buon vecchio UUID
 
il fatto di essere random non solo ti svincola da tutti i casini di 
avere una sequenza che deve essere univoca "ovunque", ma l'ID diventa 
anche opaco, con il valore aggiunto di una maggiore sicurezza contro 
attacchi
 
un altro approccio è quello di usare l'hash di un subset (campi univoci) 
dell'input: l’opacità è mantenuta e in più si ha il vantaggio 
dell'idempotency,  riproducibilità e verificabilità dei flussi. A parità 
di input si ottiene sempre lo stesso risultato: piú semplice, se 
necessario, far "rigirare" i dati in caso di disaster recovery (o 
semplice debug). Ovviamente l'algoritmo di hashing deve essere robusto
 
(*) lo stesso problema simile a quello delle sequenze univoche si 
ritrova laddove sia necessario gestire un "timestamp" univoco e 
ordinato: il tempo "globale" è uno dei moderni grattacapi delle 
architetture distribuite

 
 
Ma è garantito che l'algoritmo di hash possa evitare eventuali 
collisioni (cioè che l'algoritmo implementi un hash che, a fronte di 2 
input diversi, non genera lo stesso hash)?
 
 
---
fab
 

 input diversi, non genera lo stesso hash)?
 
  la mia ultima frase recita "Ovviamente l'algoritmo di hashing deve 
essere robusto"
 
la probabilità non è mai 0% ma un algoritmo robusto è quello che rende 
la probabilità molto molto piccola
 
il rischio c’è anche con i numeri random
 
torniamo a usare le sequenze allora, chi ce lo fa fare di rischiare?
 
ok
sempre valutare pro e contro di ogni soluzione, trarre le conclusioni e 
decidere


allora... essendo l'hash di dimensione finita e i possibili payload 
infiniti, è ovvio le collisioni non possono essere impossibili. 
teoricamente parlando. nella pratica in md5 le probabilità di collisioni 
accidentali sono 1 su 2^128, che scritto così sembra un numero qualsiasi 
ma è presumibilmente la stessa probabilità che si scontrino due specifici 
atomi di questa galassia.
 
se poi si riduce lo spazio di ricerca (le probabilità assomono uno spazio 
di ricerca infinito mentre un id ha una dimensione finita e limitata) e si 
usa un algoritmo più robusto (md5 è stato rotto, anche se 
artificiosamente: 
https://www.mscs.dal.ca/~selinger/md5collision/
) ebbene 
sì,  è ragionevole assumere che sia garantito.
 
 

 la probabilità molto molto piccola 
 
Il che vuol dire che si potrebbe verificare. 
Io mi sono trovato nella situazione di dovere avere la chiave primaria del record PRIMA del suo salvataggio. Avevo iniziato a usare un UUID come chiave primaria, ma alla fine ho risolto con una tabella che teneva, per ogni record, conto degli id di tipo long (64 bit) già rilasciati e una piccola stored procedure che, su richiesta, restituiva un indice sicuramente univoco (ti do il valore e aumento di uno l'indice nella stessa transazione).
 
Certo, qualche id te lo giochi, e prima o dopo in collisione ci va, ma ho calcolato che per un centinaio di anni dovrei essere stato al sicuro...

 attacchi
 
si sono sostanzialmente d'accordo sul fatto che un id di una risorsa abbia 
senso essere globalmente univoco. un progressivo per forza di cose è 
legato alla struttura della tabella / database più che all'entità stessa, 
ovvero ogni volta che tu inserisci quell'entità in una tabella deve essere 
visto come "nuovo" e riassegnato l'id. 
mi incuriosiva la precisazione "db relazionale" perché, storicamente 
parlando, se c'è una scuola di pensiero in cui si afferma quest'ultimo 
concetto è proprio quella relazionale "ortodossa". 

 nella stessa transazione).
 
va beh il classico numeratore. si usa quando è mandatorio non avere buchi. 
ma per un id che valore aggiunto da rispetto ad una sequence?

 ma per un id che valore aggiunto da rispetto ad una sequence?
 
Sostanzialmente che, se per qualsiasi motivo mi serve l'ID PRIMA di qualsiasi salvataggio (raro, ma a me è capitato), allora ce l'ho di sicuro indipendentemente da cosa faccio dopo. Un valore da sequence entra in gioco solo quando avviene il salvataggio. So che ci sono metodi che ti consentono di avere l'ultimo ID usato (almeno in SQL Server e in Postgres, gli altri non li conosco), però secondo me in questo modo il rischio di concorrenza è più elevato.

 rischio di concorrenza è più elevato.
 
ma non è vero... la sequence la puoi consumare quando vuoi con una 
semplice query sql. ti serve prima, la consumi prima chiamando 
direttamente il nextval che ti restituisce direttamente il valore 
incrementato con la garanzia che non lo darà a nessun altro.
l'unico "problema" è che non è transazionale e se fai rollback non torna 
indietro e il numero prenotato è bruciato. ma questo si sa, le sequence 
non sono adatte per gestire numeratori dove non puoi avere buchi. però 
l'univocità è garantita certamente.
 
 
 

 l'univocità è garantita certamente.
 
Ma alla fine, a che servono i numeratori? Intendo: una chiave primaria è importante che sia univoca, non necessariamente che sia in ordine.

Il 03/01/22 10:32, Luca Menegotto ha scritto:

Va bene,ma allora perche hai scritto che gli id non dovrebbero essere 
usati ?
 
 
-- 
|___|

 importante che sia univoca, non necessariamente che sia in ordine.
 
per esempio per il numero fattura. in quel caso devi generare un 
progressivo e non puoi avere buchi.


No, li allora devi avere un progressivo che sia differente e gestito differentemente. Anche perché non è detto che tu abbia a che fare con una società unica.
Ironia della sorte, proprio in questo periodo mi sto occupando di fatturazione, e ho a che fare con un numero di società che emettono fatture al momento pari a 3 ma destinato ad aumentare.

 una società unica.
 
sì il classico contatore, una tabella in cui hai una riga per ogni 
contatore contenente l'ultimo valore che a quel punto incrementi in 
transazione (select for update -> update). 
 

Il 05/01/22 20:55, rootkit ha scritto:

da che mi risulta il "numero fattura" può contenere buchi, e può non 
essere un numero (nella sua interezza)
e che sia univoca all'interno delle fatture emesse dal medesimo soggetto 
(P. IVA)
 
  della legge 24 dicembre 2012, n. 228 - per le
operazioni effettuate a partire dal 1° gennaio 2013, la fattura deve 
contenere "un
numero progressivo che la identifichi in modo univoco"
 
quindi una numerazione di questo tipo è perfettamente legittima
 
20220101IC0001
20220101MP0004
20220110010005
202202120001
AA29200109FF
 
 
ho un cliente che emette la numerazione fattura identificando 
all'interno del numero stesso di che prestazione si tratti
 
un esempio
20220101MP0004
 
20220101 (anno-mese-giorno)
M (identificativo lavoro M=muratura I=idraulica E=elettrica)
P (tipologia cliente P=privato, C=condominio)
0004 (progressivo_fattura)
 
nel software che ho creato ho cercato di rispettare il più fedelmente 
possibile la normativa
quindi gli ultimi 4 byte sono numerici "progressivi" di default ma 
possono essere editabili con l'unico vincolo che a parità di 
identificativo fattura "20220101MP" il numero deve essere superiore (non 
necessariamente successivo) ad uno già inserito e correttamente inviato 
all'agenzia delle entrate.
 
 
 
 
 
 
 
 
 

<<Il 08/01/2022 11:55, bramante ha scritto:
 
e per la progressività?
 
cioè tra le seguenti due fatture , come faccio a sapere quella emessa 
per prima?
 
 
  20220101IC0200
  20220101MP0004

 da che mi risulta il "numero fattura" può contenere buchi, 
 
si il mio era un retaggio del passato, ora sicuramente con la fatturazione 
elettronica e col fatto che le fatture transitano dall'ade non c'è più 
esigenza. un tempo era così, essendo il tuo archivio il riferimento la 
finanza al controllo voleva la certezza che tu non nascondessi roba.
 
in tempi più recenti abbiamo avuto questa esigenza nella protocollazione 
di un documentale.
 
 

 (*) Sì, lo so. Io sono della scuola di pensiero che afferma: 'gli ID incrementali, in un DB relazionale, non dovrebbero MAI essere usati'; tuttavia, ne viene fatto largo uso e non sono in effetti così scomodi.
 
"Ne viene fato largo uso e non sono in effetti cosi` scomodi" cozza con 
"non dovrebbero MAI essere usati".

 avere una sequenza che deve essere univoca "ovunque"
 
Se hai un sistema altamente distribuito (cosa comune oggi), generare un 
id random come un UUID puo` essere una buona scelta, ma in casi in cui 
non sia richiesto, affidarsi al generatore di sequenze del db e` 
assolutamente la cosa migliore da fare. Riguardo all'opacita` del dato, 
non e` un problema, perche` il valore della chiave primaria non dovrebbe 
MAI emergere. E` solo usato internamente per mantenere integrita` 
referenziale.

 "non dovrebbero MAI essere usati".
 
No. Seguimi. 
Il tipo int non va mai usato perché è troppo piccolo. Normalmente in questo momento i tipi int sono signed a 32 bit, il che vuol dire che che hai due miliardi e rotti di operazioni disponibili, e poi hai terminato le risorse. Molto, molto meglio un tipo long signed a 64 bit, così hai molto più gioco.

Normalmente in questo momento i tipi int sono signed a 32 bit
 
"Normalmente" un un bel niente. Non esiste "il tipo int" e assumere che 
un tipo intero sia di 32 bit non ha senso. La lunghezza di un intero 
varia da sistema a sistema e molto spesso i database hanno un proprio 
tipo numerico a precisione estesa. Per esempio, Oracle ha NUMBER, che 
con le sequence arriva fino a 28 cifre. Il massimo per un 
autoincrementale in SQL Server e` 9223372036854775807. La stessa cosa 
per Postgres, in cui puoi avere sia bigint che bigserial.
 
Ma anche se, come erroneamente affermi, si fosse fermi a 32 bit, ti ci 
voglio vedere ad inserire 2 miliardi e passa di entita` in una tabella 
del tuo sistema. Significa comunque lavorare su un sistema di nicchia, 
per cui fare affermazioni generali non ha senso. Come gia` detto, non 
c'e` assolutamente ALCUN problema ad usare id autoincrementali in un 
database relazionale. Anzi, vanno usati a meno di ragioni MOLTO 
specifiche per non farlo.
 

 specifiche per non farlo.
 
Discorso già fatto. La prima parte non l'ho mai negata, circa la seconda, convinzione tua, che rispetto.

 circa la seconda, convinzione tua, che rispetto.
 
Non e` una convinzione mia. E` il motivo per cui i database relazionali 
offrono id autoincrementali. Devi imparare a supportare quel che scrivi 
con argomenti tecnici concreti e solidi e non arrampicarti sugli 
specchi, specialita` di questo ng peraltro.
 

 Non e` che ci vuole molto. E` che quel che scrivi non ha senso.
 
VAAAAA BENE!!!
 
Guarda, hai ragione tu. Non ho ne tempo ne voglia di mettermi a far polemiche. 
Mi fermo qui e non proseguo oltre.

 incrementale di un database sia necessariamente un intero di 32 bit.
 
potrà anche non aver senso assumerlo, ma è esattamente il caso riportato 
dall'op.

 dall'op.
 
Certo, se il problema e` usare il tipo giusto per memorizzare quel 
valore siamo d'accordo. Ma dal problema esposto, non si deduce affatto, 
come ha scritto Menegotto, che non si debba mai usare ID 
autoincrementali con un db relazionale, una sciocchezza bella e buona.
 

 Mi sa che il tale non conosce la differenza tra i vari tipi interi
 
La differenza tra i vari tipi di interi non c'entra una beneamata mazza.
 
Hai scritto "NESSUNO che usi un database relazionale utilizzerebbe un ID 
incrementale di tipo int" e "gli ID incrementali, in un DB relazionale, 
non dovrebbero MAI essere usati", due idiozie belle e buone che non puoi 
giustificare in nessun modo.
 
Tra l'altro, hai la pretesa che questa sia una "scuola di pensiero". 
ROFL :)
 
Taci, va', che e` meglio.
 
 

 Guarda, hai ragione tu.
 
Certo che ho ragione io. E lo sai bene. Solo che qui dentro gli errori 
non si ammettono mai in maniera pacifica, bisogna morire con la spada in 
mano, scoreggiando.
 

 giustificare in nessun modo. 
 
Ok, come hai visto la prima non era un'idiozia. La seconda nemmeno. 
Se tu progettavi databases, sicuro fino a 20 anni fa, probabilmente anche successivamente, la best practice era la progettazione di chiavi primarie costituite dal minimo subset di campi che fosse univoco. Se ne parlava con Root in uno dei messaggi precedenti. E, per lungo tempo, l'impiego degli ID numerici è stato visto come il male proprio perché non consentono di capire, a un primo sguardo, di cosa si sta parlando. Una progettazione del genere ha un unico, e in effetti enorme, inconveniente: ti dovesse accadere di modificare per qualunque motivo la chiave primaria, devi toccare quella (e sarebbe il meno) e anche TUTTI i riferimenti ad essa. 
Che è un lavoro probabilmente immane, soprattutto se il numero di tabelle è piuttosto numeroso. Certo, se devi fare modifiche del genere, parecchio lavoro va comunque fatto, perché per certo si dovrà mettere mano a qualche indice e a parecchia parte di programmazione (penso specificamente a funzioni, a stored procedures e alla integrità referenziale), ma forse è meno.
 
E non ho altro da dire su questa faccenda.
 

Il 08/01/22 21:01, vittorio ha scritto:

all'interno del file xml che invii all'agenzia delle entrate c'è il 
campo della data del documento
 
fa fede quello

 di un documentale.
 
una curiositá, come l'avete risolta? se non ci devono essere buchi 
caschi il mondo pure se un raggio cosmico colpisce il server e scambia i 
bit (è successo veramente più di una volta...) l'unica soluzione che mi 
viene in mente è quella di staccare i codici /a priori/ e poi aggiornare 
il documento quando la fattura è emessa e "cristallizzata". ma non ho 
idea se si possa fare, i miei ricordi di contabilità risalgono a decenni 
fa e se non sbaglio le fatture sono "immodificabili" e "cristallizzate" 
alla nascita (per ovvi motivi di legalità)

Il 13/01/22 21:13, M C ha scritto:

la FATTURA di per se è un documento che attesta il pagamento a fronte di 
una cessazione di bene o servizio, di per se è modificabile come e 
quando vuoi, anche perché gli stessi beni e servizi possono essere 
mutevoli nel tempo e nel contenuto.
 
dal momento che la fattura viene contabilizzata, non può essere modificata.
 
e anche in quest'ultimo caso puoi emettere una nota di credito/debito 
per modificarne importo e contenuto della stessa una volta contabilizzata.
 
 

Il 13/01/22 14:13, M C ha scritto:

Mai sentito parlare di transazioni con begin commit/rollback nonche di 
lock ?
 
 
-- 
|___|

 una cessazione di bene o servizio
 
da leggersi "cessione" ?
 
-- 
/-\ /\/\ /\/\ /-\ /\/\ /\/\ /-\ T /-\
-=- -=- -=- -=- -=- -=- -=- -=- - -=-
........... [ al lavoro ] ...........

 lock ?
 
E questo che cazzo c'entra con i numeratori, imbecille? Se vuoi 
controllare la sequenza devi "accodare" i lavori. Testona di cazzo!
 
-- 
The three most dangerous things in the world are a programmer with a 
soldering iron, a hardware type with a program patch and a user with an 
idea.
 
“Alles hat ein Ende, nur die Wurst hat zwei”
 
 

 lock ?
 
ti faccio notare che qualche post piu' in su qualcuno ha menzionato che 
il valore di una sequenza una volta preso e' bruciato, le usi o non lo 
usi: se fai rollback ti trovi un buco
 
se non fosse cosi' sai i bordelli - che ci sono comunque - con 
transazioni aperte/chiuse, sequenze che vanno avanti, indietro, si 
bloccano...
 
mi viene in mente la barzelletta del tipo con tre palle

 
 
 
 
Genio,come fai a garantire una sequenza senza buchi dentro un codice sql 
generico  senza transazioni ?
 
 
-- 
|___|

 mi viene in mente la barzelletta del tipo con tre palle
 
 
-- 
|___|

 la FATTURA di per se è un documento che attesta il pagamento a fronte di 
 
ATTESTA UN CREDITO, NON UN PAGAMENTO

 
 
CHE MALEDUCATO

 una curiositá, come l'avete risolta? 
 
quelli che si chiamavano numeratori. una tabella con una riga per ogni 
numeratore, es. annuale, due colonne anno e progressivo. quando volevi 
prendere un numero, select for update, incremento di uno, updrate della 
riga, quindi salvataggio del documento. se succede qualcosa nel 
salvataggio rollback e non è successo nulla. la select for update ti 
garantisce il lock sulla riga in modo che nessun altro in concorrenza 
possa fare la stessa cosa ma si accoda in attesa che la transazione sia 
finita (oppure fallisce, se ha l'opzione nowait). 
 
l'opzione for update per la select è sicuramente presente su oracle  
postgres e sql server.

 postgres e sql server.
 
Uhm... in T-SQL non ne sono così sicuro. E non risulta manco dalla documentazione.
In effetti, a leggere è interessante, perché altro non fà se non mettere un lock esclusivo sulla tabella che viene utilizzata. Pericolosetto, se non sai quel che fai, ma decisamente potente, se rinchiuso in una transazione.
La mia certezza si solidifica: Postgres è un grandissimo DBMS...

 transazione.
 
lo fa a livello di riga. certo se lo fai senza mettere clausole di 
where... così come se progetti batch che tengono la transazione per minuti 
o ore, cosa che non è vietata di per se ma si deve essere consapevoli che 
la concorrenza aspetta.
 

 la concorrenza aspetta.
 
Il problema è che il 'colpo de mona' è sempre in agguato... 
 
:-DDDD
 

 postgres e sql server.
 
si, si la conosco e la uso
pero', scusa, se fai la select update per fare +=1 su un campo che 
presumibilmente fa parte della chiave primaria composta, significa che 
stai facendo una select non univoca - che puo' restituire piu' righe
 
es.
 
pk1,pk2,pk3,....
pippo,2022,1234,....
 
vuoi incrementare 1234->1235
 
se fai la select update, immagino, per calcolare max(pk3) quando 
pk1=pippo e pk2=2022 ti tira su tutti i progressivi comunque per 
calcolare il max...
 
 
o non c'ho capito na mazza

 calcolare il max... 
 
Ci vedo un po' di confusione.
Usare la funzione MAX per il calcolo di qualcosa che è in una chiave primaria è profondamente errato. In questo caso si deve utilizzare una tabella di numeratori di appoggio (ad esempio, una tabella composta con tre campi pk1, pk2 e l'ultimo indice utilizzato). Il motivo è proprio prestazionale, e l'hai intuito anche tu. Questo è vero soprattutto nel caso in cui quell'indice non è univoco (la sua univocità è se presa in considerazione con pk1 e pk2 o, detto in altro modo, lo stesso valore pk3 può comparire più volte).
Se tu crei la tabella degli indici progressivi, allora sei sicuro di andare a prendere uno ed un solo record.


quella dei progressivi è una tabella dedicata.
 
avresti una tabella con due colonne: anno, progressivo. su questa tabella 
faresti:
 
select progressivo from tabella where anno = '2022' for update;
 
a questo punto avresti un lock esclusivo sulla riga per la transazione 
(come se avessi fatto un update) e il progressivo letto non può cambiarlo 
nessuno.
 
procedendo:
 
update tabella set progressivo = progressivo + 1 where anno = '2022';
 
quindi procedi nella transazione consumando il progressivo.
 
alla fine, commit o rollback. in caso di rollback anche l'update torna 
indietro e un eventuale concorrente leggerebbe il valore precedente.
 
si tratta in sostanza di simulare una sequence ma transazionale, perché le 
sequence non lo sono.
 
 

 Usare la funzione MAX per il calcolo di qualcosa che è in una chiave primaria è profondamente errato.
 
lo so benissimo
infatti ho chiesto per chiarire
alle 11 di sera dopo un torneo di scacchi online dall'esito disastroso 
poteva succedere di tutto... :-)

 sequence non lo sono.
 
ho capito
(è mattina adesso...)
questa tecnica si può probabilmente usare in congiunzione con un UPDATE 
RETURNING ma non tutti i dialetti lo supportano
 
tipo
 
UPDATE dummy SET counter=sub.next_value FROM
(SELECT counter+1 AS next_value FROM dummy WHERE whatever='2022' FOR 
UPDATE) sub WHERE whatever='2022' RETURNING counter
 
usi counter nella INSERT, il tutto dentro una transazione
se qualcosa va storto amici come prima e counter torna al valore di partenza

 RETURNING ma non tutti i dialetti lo supportano
 
più che in congiunzione in sostituzione. come anche il "for update" non 
tutti i dialetti lo supportano, è il modo di rendere atomica lettura e 
scrittura del dato.
 

 Per il resto: così disastroso, il torneo di scacchi?
 
Si, da dimenticare
 
Non la pizza e birrozza che ho avuto prima del torneo peró...
 

 Ma infatti il FOR UPDATE nella sub-query SELECT garantisce proprio quello 
 
Son d'accordo. Avevo scritto una minchiata, e me ne sono reso conto dopo l'invio. L'avevo cancellato, ma evidentemente la cancellazione non è generale. 
Perdono.

 
  posso chiederti la categoria?
se non chiedo troppo ovviamente
 
e2-e4 forever (col bianco)
 

 e2-e4 forever (col bianco)
 
e7-e5...

 e2-e4 forever (col bianco)
 
mai preso la briga di inscrivermi alla federazione... non c’è l'ho una 
categoria... (gioco su Lichess)
 
e4 l'ho abbandonato da tempo, troppa teoria
 
sono pigro, Cf3 col bianco e Caro Kann col nero (contro e4)


accodando



Anche du DB2


 accodando
 
Accodare significa mettere un semaforo (un lock) ma non risolve la 
coerenza dei dati in caso di piu operazioni
 
 
-- 
|___|


Ci sono oggetti appositi per eseguire un'accodamento in sicurezza. 
Ignorante come una capra!


 Ignorante come una capra!
 
 
Ma certo, ma ci pensa gia il db a mettere i lock e a garantire la 
coerenza dei dati attraverso le transazioni
Perche inventarsi altre cose ?
Tu se progetti un db non usi le transazioni ?
Se la risposta e' no cosa usi ?
Vai a dare il tuo progetto a dei clienti e gli spieghi che non usi le 
transazioni
Lo sai cosa ti risponde il tecnico competente di db ?
Probabilmente sai lui a darti dell' ignorante come una capra
 
 
 
-- 
|___|

 Perche inventarsi altre cose ? 
 
Perché le transazioni possono essere concorrenti e possono fallire.
 

 
 
Non posso farti da Tutor, sei troppo imbecille!


Il 17/01/22 13:06, Luca Menegotto ha scritto:

La transazione non ha nulla a che fare con la concorrenza
La transazione serve solo per la coerenza dei dati
Sono i semafori che regolano la concorrenza
E se una transazione fallisce occorre capirne i motivi,non e' certo 
colpa delle transazioni in se
 
 
 
 
 
-- 
|___|

 colpa delle transazioni in se 
 
E questo cosa c'entra col mantenere la coerenza di un progressivo in modo che non ci siano buchi?

 ATTESTA UN CREDITO, NON UN PAGAMENTO
 
una nota di debito (che è una FATTURA collegata ad una precedentemente 
emessa) di solito ha un importo negativo, non lo chiamerei proprio credito.
 
una fattura può anche essere negativa fin dall'inizio
 
pensa ad esempio ad un conguaglio dove il cliente va a credito e quindi 
l'azienda emette una fattura negativa
 
non ti è mai capitato di ricevere una bolletta con importo negativo?
 
 

Il 16/01/22 12:03, M C ha scritto:

per un progetto che mi sono occupato diversi anni fa da un cliente
 
è stato risolto facendo gestire il progressivo all'atto della insert in 
transactional mode.
 
max(id) + 1 come trigger in before insert sulla tabella.
 
e gestendo la queue del servizio che gestisce le fatture (microservice).
 
non esiste concorrenza in quanto il servizio elabora una fattura per volta .
 
se arrivano anche 1000 fatture in contemporanea si accodano  (message 
queue) al servizio che le gestisce sia che si tratti di batch processing 
sia di oltp.
 
se tutto va bene viene emessa la fattura, se qualcosa va male, scarta e 
passa alla successiva (senza buchi) e scrivendo un log degli scarti.
 
se ci si pensa l'emissione della fattura non è una necessità di real time.
 
nel contesto oltp l'operatore inserisce tutti i dati della fattura (o le 
fatture se sono più di una) e la sottomette, successivamente quando 
pronto gli arriva la notifica con l'emissione e il numero delle fatture 
(o l'eventuale errore).
 
in genere nel giro di al max 2 minuti se c'è tanta coda (qualche 
migliaio di fatture, nei test fatti).
 

 non ti è mai capitato di ricevere una bolletta con importo negativo?
 
io l'ho sempre chiamato rimborso, ma sono una persona semplice

 max(id) + 1 come trigger in before insert sulla tabella. 
 
Per come la vedo io, questa soluzione funziona a patto che quel valore calcolato non ti serva da altre parti.

 sia di oltp.
 
 
ok, ma se è il sistema di code a garantire l'integrità allora è forviante 
mettere questa logica nel trigger. cioè se io vengo da fuori e vedo che è 
il trigger a valorizzare l'id, mi aspetto che chiunque scriva l'integrità 
è garantita. il che non è vero. oltretutto il fatto che venga elaborata 
una fattura alla volta non è garantito dalla coda ma dal fatto che ci sia 
un solo consumer.


E' un cazzo di genio !



Hai fondamentalmente ragione.
Immagino pero' che l'architettura dell'applicazione imponga che il db in 
questione non sia aperto ad interfacce esterne, in tal caso ogni 
richiesta dall'esterno dovra' obbligatoriamente rivolgersi ad un 
servizio applicativo che se ne occupi, con le sue code, i suoi trigger e 
tutto il resto. In pratica la logica relazionale sta' nell'applicazione 
e non nel db dove dovrebbe stare.
Esistono applicazioni gestionali che allo scopo (ahime'!) impongono 
l'uso di tabelle di frontiera (spesso dette "input di massa") che 
vengono elaborate da appositi programmi. Se tale soluzione, si fa per 
dire, ti fa' cagare, accomodati, da parte mia ho gia' fatto!
:-)

Il 19/01/22 09:34, rootkit ha scritto:

forse mi son spiegato male
 
il trigger è nel microservice della gestione delle fatture
invece di gestire una entità contatore (che sia una sequence una tabella 
contatore o altro) è stato deciso di usare un trigger before insert, 
all'atto dell'inserimento del record.
 
 

Il 19/01/22 10:12, Dr.UgoGagliardelli ha scritto:

la logica relazionale sta nel db
 
web
API     --> message queue --> microservice fatture --> DBMS
other

 dell'inserimento del record.
 
ah quindi più che un trigger un interceptor nel codice (come si possono 
fare con spring e/o hibernate).
la parola "trigger" mi fa venire in mente subito il db.
 

Il 18/01/22 13:30, Luca Menegotto ha scritto:

Centra perche in un progetto realistico oltre all'aggiornamento del 
progressivo si faranno altre operazioni
Ora, per mantenere la coerenza dei dati occorre usare le transazioni
 
 
-- 
|___|

 la parola "trigger" mi fa venire in mente subito il db.
 
Cosa intendi?


che per me i trigger sono quelli che si mettono alle tabelle dei database.

 che per me i trigger sono quelli che si mettono alle tabelle dei database.
 
Ah, ok. 
A me quello E gli oscilloscopi.
Mai usato uno, ma avendo lavorato in un'azienda che fa elettronica industriale, so che esistono.

 
 
esatto, un trigger nel dbms

 A me quello E gli oscilloscopi.
 
E' anche quello che mettono sotto le pistole ;o)



Non completamente, se accedo direttamente al db tramite interfaccia 
esterna, tipo odbc, jdbc, cli o altro programma ma anche una stored 
procedure o UDF, la logica dell'accodamento (message queue) e 
microservice fatture vengono ignorati.