https://github.com/pioz/test_duplicate_entry Praticamente e` una rails app vuota con devise preconfigurato. Unicorn come app server. Tramite lo scriptiono vengono fatte 1000 richieste per creare lo stesso utente in parallelo. Dopo un po' capita l'eccezione maledetta! Ci stiamo sbattendo la testa da un po'.. Se qualcuno di voi ha tempo da perdere qualsiasi aiuto e` il benvenuto. Ciao Raga grazie
on 2013-01-24 18:31
on 2013-01-24 18:41
Che versione di Mysql e` con quale engine? Mi viene sempre il sospetto... Flame wars: meglio Postgresql:-) 2013/1/24 Davide Barison <davide@megiston.it>: > Se qualcuno di voi ha tempo da perdere qualsiasi aiuto e` il benvenuto. > > > > _______________________________________________ > Ml mailing list > Ml@lists.ruby-it.org > http://lists.ruby-it.org/mailman/listinfo/ml > -- David N. Welton http://www.welton.it/davidw/ http://www.dedasys.com/
on 2013-01-24 18:43
Mysql-server 5.1.66 Adapeter: mysql2 (0.3.11) Il 24/01/13 18:40, David Welton ha scritto:
on 2013-01-24 18:54
Ruby 1.9 and Rails 3.2.11 Per la precisione stiamo usando ruby 1.9.3p125 Il 24/01/13 18:43, Fabrizio Regini ha scritto:
on 2013-01-24 19:02
Abbiamo provato anche con un altra versione di mysql server
mysql Ver 14.14 Distrib 5.5.19, for osx10.7 (i386) using readline 5.1
Adapter mysql2 0.3.11
PS: per riprodurre l'errore piu` volte cancellate l'utente creato, e
rieseguite lo script.
Per chi non ha capito:
* La prima richiesta l'utente viene creato.
* La seconda richiesta devise dovrebbe fare scattare un errore di
validazione tipo "email already taken" e cosi` per tutte le altre..
* Dopo un po' di richieste scattano le eccezioni di duplicate record..
Il 24/01/13 18:54, Fabrizio Regini ha scritto:
on 2013-01-24 19:13
Altre info: stiamo sospettando un problema di race condition sul devise|:validatable se togliamo il fork dallo scriptino e facciamo 1000 richieste sequenziali nessun problema. | Il 24/01/13 19:00, Davide Barison ha scritto:
on 2013-01-24 21:45
Problemi con il fallimento dei validate uniqueness I me ne ricordo da parecchio tempo. Ed infatti: https://github.com/rails/rails/blob/0bb15174558fde... Devi sempre mettere un indice unico a livello di database se vuoi stare sicuro. -f
on 2013-01-24 21:45
Ok, ma con quale storage engine? InnoDB? Quello almeno ha le transazioni. Sort of... l'ultima volta che ho guardato, non c'erano per le migrazioni. 2013/1/24 Davide Barison <davide@megiston.it>: >>> >>> Ciao Raga grazie >>> >> http://www.welton.it/davidw/ > Twitter <http://twitter.com/davidebarison> Facebook > -- David N. Welton http://www.welton.it/davidw/ http://www.dedasys.com/
on 2013-01-24 22:40
Ciao, Il 24 gennaio 2013 19:12, Davide Barison <davide@megiston.it> ha scritto: > Altre info: > > stiamo sospettando un problema di race condition sul devise|:validatable > se togliamo il fork dallo scriptino e facciamo 1000 richieste > sequenziali nessun problema. Avete ragione: si tratta di una race condition causata dall'uso di validazioni di unicit; un problema noto, descritto nella documentazione ( http://bit.ly/XD8AAx ). Arriva una richiesta di creare l'utente your@mail.com; prima di creare il record sul db, ActiveRecord::Validations controlla che non esista gi, eseguendo una query sul db. Se trova che quell'email c' gi, d un errore di validazione, altrimenti inserisce il record con un'altra query al db. Se le richieste vengono servite in concorrenza, le operazioni sul db possono accavallarsi, per cui due richieste controllano se esiste gi your@mail.com, entrambe vedono che non esiste, la prima crea il record, la seconda crea il record. A quel punto tutto dipende dal db, e ci sono due possibilit: o sul db non ci sono vincoli; in questo caso vengono creati dei duplicati, e il db sar inconsistente; o invece sul db ci sono vincoli di unicit, e allora si avranno errori db ossia eccezioni come quella che capita a voi, ma in compenso il db rester consistente. Lanciando mille richieste contemporaneamente, le probabilit che ci sia almeno un accavallamento enorme; nella vita quotidiana, invece, a molte applicazioni web non capita neanche una volta. La documentazione di cui sopra suggerisce di catturare ActiveRecord::RecordNotUnique per dire all'utente che i dati sono duplicati. pietro
on 2013-01-24 22:50
Grazie Pietro mi hai illuminato! Purtroppo stiamo cercando di affrontare questo problema perche` abbiamo delle eccezioni in produzione che stanno aumentando. Il 24/01/13 22:39, Pietro Giorgianni ha scritto:
on 2013-01-25 09:48
2013/1/24 Pietro Giorgianni <giorgian@gmail.com>: > validazioni di unicit; un problema noto, descritto nella > documentazione ( http://bit.ly/XD8AAx ). A parte che prendere l'eccezione un approccio OK, In realt io non capisco perch dovrebbe succedere anche specificando livelli di serializzabilit pi forti per la transazione, e.g. SELECT FOR UPDATE o ISOLATION LEVEL SERIALIZABLE in mysql Qualcuno ne capisce pi di me? -- twitter: @riffraff blog (en, it): www.riffraff.info riffraff.blogsome.com work: circleme.com
on 2013-01-25 10:08
2013/1/25 gabriele renzi <rff.rff@gmail.com> > A parte che prendere l'eccezione un approccio OK, In realt io non > capisco perch dovrebbe succedere > anche specificando livelli di serializzabilit pi forti per la > transazione, e.g. > > SELECT FOR UPDATE o ISOLATION LEVEL SERIALIZABLE in mysql > > Qualcuno ne capisce pi di me? a rischio di dire una cavolata, ma ... "select for update" non dovrebbe funzionare perche' la situazione e' che non ci sono ancora record selezionabili quando viene fatta la query, quindi non viene lockato nulla i.e. piu' di una select for update ha successo allo stesso tempo [*]. Usando "isolation level serializable" il blocco non e' al momento della select di validazione ma al momento della insert, i.e. l'eccezione c'e' lo stesso. Luca
on 2013-01-25 10:30
Il 25 gennaio 2013 09:47, gabriele renzi <rff.rff@gmail.com> ha scritto: > A parte che prendere l'eccezione un approccio OK, In realt io non > capisco perch dovrebbe succedere > anche specificando livelli di serializzabilit pi forti per la > transazione, e.g. > > SELECT FOR UPDATE o ISOLATION LEVEL SERIALIZABLE in mysql > > Qualcuno ne capisce pi di me? Ciao, io non sono un esperto di magie col db, quindi magari qualcun altro ti sa rispondere meglio. Posso fare solo due considerazioni: 1. Quello che vorresti, se ho capito, poter fare due query consecutive senza che nessun altro possa fare query nel frattempo. Non so se questo possibile o se facile in rails, ma mi viene da dire questo: se in questo momento in produzione avete i problemi che descrivevate prima, vuol dire che avete tante richieste ravvicinate; passare a una soluzione in cui le varie richieste allocano il db in modo esclusivo, con ogni probabilit non farebbe altro che cambiare il tipo di exception con cui litigare, perch il db a quel punto sarebbe occupato per molto pi tempo, e rischiereste di avere richieste fallite per la troppa attesa sul db. 2. L'operazione "inserisci un record nel db solo se non ce n' gi uno con quel valore l" gi supportata dai db: esattamente a questo scopo che hanno introdotto i constraint. [Attenzione: pericolo di flame nel paragrafo che segue!] Decenni dopo arrivata la community rails e ha deciso che no, le cose fatte bene sono brutte, invece le cose broken by design sono pi in, tanto che in un sacco di posti si trova scritto che un vero rails programmer non dovrebbe usare i constraint, perch blasfemo far fare al db quello che non si pu fare a livello applicativo... Insomma, io vi suggerisco di intercettare l'eccezione e via. pietro
on 2013-01-25 11:41
2013/1/25 Pietro Giorgianni <giorgian@gmail.com>: > Ciao, > modo esclusivo, con ogni probabilit non farebbe altro che cambiare il > tipo di exception con cui litigare, perch il db a quel punto sarebbe > occupato per molto pi tempo, e rischiereste di avere richieste > fallite per la troppa attesa sul db. Il mio problema solo relativo a quello che dice la documentazione di AR: date due transazioni con select & insert che avvengono concorrentemente se una delle due blocca tutta la tabella in write mode non mi chiaro perch l'altra dovrebbe andare avanti da se per un po' in maniera concorrente. Ma come dice anche Luca, plausibilmente si intende che parte un'eccezione di "not serializable" piuttosto che "record not unique" che non cambia la sostanza. Chiaramente non suggerisco di mettere livelli di transazione sempre pi alti e passare tutto da un singolo lock globale, la mia era solo una curiosit :) > 2. L'operazione "inserisci un record nel db solo se non ce n' gi uno > con quel valore l" gi supportata dai db: esattamente a questo > scopo che hanno introdotto i constraint. [Attenzione: pericolo di > flame nel paragrafo che segue!] Decenni dopo arrivata la community > rails e ha deciso che no, le cose fatte bene sono brutte, invece le > cose broken by design sono pi in, tanto che in un sacco di posti si > trova scritto che un vero rails programmer non dovrebbe usare i > constraint, perch blasfemo far fare al db quello che non si pu > fare a livello applicativo... assolutamente d'accordo con te. -- twitter: @riffraff blog (en, it): www.riffraff.info riffraff.blogsome.com work: circleme.com
on 2013-01-25 13:51
Il giorno 25 gennaio 2013 10:39, gabriele renzi <rff.rff@gmail.com> ha scritto: > > constraint, perch blasfemo far fare al db quello che non si pu > > fare a livello applicativo... > > > assolutamente d'accordo con te. Esistono constraint e constraint. E' passato un periodo in cui qualche malato faceva delle verifiche applicative (es. et >= 18) con le constraint, e poi usava le ECCEZIONI per gestire gli errori di validazioni. E' un approccio che insegnano all'universit, ed SBAGLIATO: usare le eccezioni per tutto ci che non 'eccezionale' un errore, perch queste sono 'costose'. Le verifiche "applicative" vanno fatte a livello applicativo, da cui le validazioni in rails. Al contrario, un approccio sensato usare le constraint a livello di database per garantire la consistenza, se qualcosa va storto il nostro db deve rimanere sempre consistente. Quindi, ok a 'unique', 'foreign keys', ecc.. Nel caso queste siano violate, per me tranquillamente OK andare in eccezione anche nei confronti dell'utente finale, cos mi arriva una bella notifica e so che sta succedendo qualcosa di storto. I casi di errore 'normale' devono essere gestiti dalle validazioni a monte. Ciao, Matteo
on 2013-01-25 14:02
Il giorno 25 gennaio 2013 13:50, Matteo Collina <matteo.collina@gmail.com>ha scritto: > E' passato un periodo in cui qualche malato faceva delle verifiche > applicative (es. et >= 18) con le > constraint, e poi usava le ECCEZIONI per gestire gli errori di validazioni. > E' un approccio che insegnano all'universit, ed SBAGLIATO: usare le > eccezioni per tutto ci che non > 'eccezionale' un errore, perch queste sono 'costose'. > Le verifiche "applicative" vanno fatte a livello applicativo, da cui le > validazioni in rails. > Fin qui ok ;) Al contrario, un approccio sensato usare le constraint a livello di > database per garantire la consistenza, > se qualcosa va storto il nostro db deve rimanere sempre consistente. > Quindi, ok a 'unique', 'foreign keys', ecc.. > > Nel caso queste siano violate, per me tranquillamente OK andare in > eccezione anche nei confronti dell'utente finale, > cos mi arriva una bella notifica e so che sta succedendo qualcosa di > storto. > I casi di errore 'normale' devono essere gestiti dalle validazioni a monte. > Si. Ma Davide ha per le mani un bel caso di lettura - scrittura in concorrenza massiva (bella tosta, visto lo script di test - verifica in produzione che lancia 1000 processi in parallelo :) Presumo che lui voglia risolvere con un messaggio all'utente "non si pu fare, utente gi registrato" piuttosto che far vedere messaggio di eccezione all'utente. Il tutto mantenendo la consistenza dei dati :) Ciao, Sergio
on 2013-01-25 14:16
Il 25 gennaio 2013 14:02, Sergio Berisso <sergio.berisso@gmail.com> ha scritto: > Si. > Ma Davide ha per le mani un bel caso di lettura - scrittura in concorrenza > massiva (bella tosta, visto lo script di test - verifica in produzione che > lancia 1000 processi in parallelo :) > Presumo che lui voglia risolvere con un messaggio all'utente "non si può > fare, utente già registrato" piuttosto che far vedere messaggio di > eccezione all'utente. > Il tutto mantenendo la consistenza dei dati :) Certamente; io non sono sceso a quel livello di dettaglio perché non ho visto l'applicazione vera né lo schema db, per cui non sono in grado di dire, ad esempio, se dall'eccezione si è in grado di dire con certezza qual è il campo per cui viene violata l'unicità—potrebbe essercene più d'uno, non so—o altre cose simili. Per quel che mi riguarda, hanno due alternative molto semplici: se quell'eccezione in quell'action vuol dire sicuramente email duplicata, mostrare direttamente: "Spiacenti, l'email specificata è già in uso", come se fosse una normale validazione; se invece ad esempio hanno due campi con constraint, possono mostrare un messaggio più generico, tipo: "Il transito di Giove ha fatto sì che capitassero robe, insomma cari utenti provate di nuovo che può pure darsi che a questo giro vi vada un po' meglio". pietro
on 2013-01-25 14:41
Il giorno 25/gen/2013, alle ore 14:15, Pietro Giorgianni <giorgian@gmail.com> ha scritto: > Per quel che mi riguarda, hanno due alternative molto semplici: > se quell'eccezione in quell'action vuol dire sicuramente email > duplicata, mostrare direttamente: "Spiacenti, l'email specificata > gi in uso", come se fosse una normale validazione; beh, se anche fossero due constraint puoi sempre dire: "spiacenti, email e/o antani sono gi in uso" :P > se invece ad esempio hanno due campi con constraint, possono mostrare > un messaggio pi generico, tipo: "Il transito di Giove ha fatto s che > capitassero robe, insomma cari utenti provate di nuovo che pu pure > darsi che a questo giro vi vada un po' meglio". :-D -- http://andreapavoni.com
on 2013-01-25 15:56
Per forza di cose andreamo a catturare l'eccezione. Non capita spesso pero` capita.. la cosa strana e` che non capivamo il perche` di quell'errore visto che erano presenti le validazioni. Ora e` tutto un po' piu` chiaro grazie dell'aiuto raga Il 25/01/13 14:15, Pietro Giorgianni ha scritto:
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.