103 messaggi dal 14 aprile 2014
Buongiorno a tutti.

Da una tabella ordini ricavo l'ultimo numero ordine per assegnarlo all'ordine successivo quando l'utente apre un ordine.

Siccome gli utenti sono tanti succede (raramente ma succede) che più utenti richiedono un numero d'ordine nello stesso istante.

Si generà cosi un DEADLOCK perchè la tabella ORDINI è bloccata dalla transazione che apre il primo richiedente (il che è cosa buona e giusta ovviamente).

Il problema è che gli altri utenti vengono "buttati" fuori e devono riprendere da capo a fare l'ordine (il che è un problema... lamentele varie e via dicendo).

Mi chiedevo come fosse possibile gestire (non evitare perchè è ovviamente impossibile) il DEADLOCK in modo che posso fare aprire più ordini contemporaneamente e ricavare il numero ordine successivo senza incorrrere nel DEAD LOCK.

Immagino che (ad es.) AMAZON abbia problemi del genere avendo milioni di clienti e lo abbia gestito.

Ho cercato "in giro" Non sono riuscito a trovare una soluzione (o workaround).

Grazie a chiunque mi possa fornire qualche indicazione.

Filippo Quaranta
843 messaggi dal 08 aprile 2009
Il numero ordine lo generi alla conferma di salvataggio dell'ordine o nel momento in cui l'utente inizia a compilare l'ordine?
1.976 messaggi dal 27 luglio 2005
Contributi
salve Filippo,
tendenzialmente non mi pare una soluzione geniale assegnare il numero d'ordine al momento dell'apertura del carrello...
il carrello puo' restare potenzialmente "appeso" a lungo, e ovviamente addirittura non essere neanche confermato, quindi senza arrivare al cosidetto check-out...

detto cio', senza necessita' che corrisponda a realta', personalmente non utilizzerei in questo senso un "numero", cioe' un progressivo ordinale nel dominio numerico degli interi, ma ad esempio utilizzerei un guid generato lato server e passato al carrello...
se proprio poi ti serve un valore nel dominio numerico, al momento della conferma d'ordine provvederei a gestirne la costruzione, utilizzando anche eventualmente un'identity (che pero' potrebbe presentare dei gap) o, proprio nella peggiore delle ipotesi, calcolando il "cosidetto" max +1, ma solo al momento della conferma dell'ordine, che tendenzialmente e' un'operazione atomica che deve essere molto breve e veloce, non bloccante per altri processi, se non per la verifica di presenza e disponibilita' dei prodotti...

scrivi:
>Si generà cosi un DEADLOCK perchè la tabella ORDINI è bloccata dalla transazione che apre il primo richiedente (il che è cosa buona e giusta ovviamente).

veramente NON e' una cosa buona e giusta... a mio avviso, la tabella NON dovrebbe essere lockata... cosa devono essere "in qualche modo lockati", sono i prodotti, nel senso che non puoi vendere qualche cosa di cui tu non abbia la disponibilita'... in questo senso il modus operandi dei voli e' "funzionale"... il posto e' libero sino al momento del commit della tua operazione di prenotazione... tu "gingilli" con il tuo posto e, al momento di premere il bottone di conferma, ti viene prenotato il posto se (ancora) disponibile oppure ti viene notificata l'indisponibilita' di quanto richiesto... anche a mio parere cosi' deve funzionare, lasciando "vendibile" il prodotto per il primo che chiuda il carrello e non bloccando la vendita a potenziali clienti mentre l'utente e' andato magari a mangiare lasciando "aperta" la maschera del carrello. E vorrei pensare che tendenzialmente tutti i siti di e-commerce operino in tal senso.

salutoni romagnoli
--
Andrea
Modificato da Andrea Montanari il 19 aprile 2021 21:49 -

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
103 messaggi dal 14 aprile 2014
Ciao...

Scusate ho scritto una fesseria.

Il numero lo genero quando chiudo l'ordine.

Al SUBMIT CONCLUSIVO leggo la tabella ordini e genero il numero leggendo il NUMERO ORDINE leggendo l'ultimo numero inserito nella tabella ORDINI.

Da qui il LOCK della transazione

Che di fatto dura millisecondi (leggere l'ultimo numero e generare il numero successivo è questione di millisecondi).

Però questo non esclude che 2 utenti facciano la stessa operazione nello stesso istante da qui il DEAD LOCK.

Per questioni imposte il numero ordine deve essere un numero sequenziale partendo da 1 NON può essere quindi un GUID o similari.
Modificato da Filippo.quaranta il 19 aprile 2021 23:54 -
103 messaggi dal 14 aprile 2014
Ciao...

Scusa ho scritto una fesseria.

Il numero lo genero quando chiudo l'ordine.
843 messaggi dal 08 aprile 2009
il numero lo generi con identity o facendo il max + 1?

Io sinceramente utilizzo sempre la tecnica di fare con identity. Inserisco il mio ordine con l'identificativo primario (PK) che è un guid. Quando ho salvato ricerco tramite il mio guid e trovo il numero che mi è stato assegnato direttamente dal motore.
103 messaggi dal 14 aprile 2014
Ciao laurar181.

Faccio il MAX + 1 perchè il requisito è quello di avere ordini numerati da 1 in progressione senza interruzioni numeriche (come fosse una fattura).

Ma per avere il numero successivo devo avere prima "salvato" l'ordine precedente.

Per cui se 3 utenti concorrenti fanno la richiesta 2 potrebbero (è questione di millesimi di secondo) incorrere nel DEAD LOCK della precedente transazione in corso sull'ordine in inserimento.

Da qui il mio (potenziale) problema.

Filippo
1.976 messaggi dal 27 luglio 2005
Contributi
salve Filippo,
Filippo.quaranta ha scritto:

...
Ma per avere il numero successivo devo avere prima "salvato" l'ordine precedente.
...


a dire il vero NO...

il tuo ordine sara' sicuramente composto da un testa e dettagli...
al momento dell'inserimento della testa, in uscita del comando di INSERT ritorni SCOPE_IDENTITY ( https://docs.microsoft.com/it-it/sql/t-sql/functions/scope-identity-transact-sql?view=sql-server-ver15 ), che sara' la PK del tuo ordine e ovviamente colonna relazionata nei dettagli...
inserendo i dettagli, userai il valore di SCOPE_IDENTITY che prima hai ottenuto per inserire ogni dettaglio facente riferimento al tuo ordine di testa...

cerca di NON lockare niente o il meno possibile... chiaramente il tuo salvataggio completo di testa e dettagli sara' in transazione in modo da risultare un'unica operazione atomica, ma non di piu'...

@laurar181: e non c'e' bisogno di avere anche un'altra colonna per fare "la ricerca del valore" identity assegnato alla riga... basta ottenerlo "all'uscita" del comando di INSERT...

salutoni romagnoli

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.