Forum: Italian Ruby user group Raga help ci stiamo scervellando su questo problema

Posted by Davide Barison (Guest)
on 2013-01-24 18:31
Attachment: signature.asc (299 Bytes)
(Received via mailing list)
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
Posted by David Welton (Guest)
on 2013-01-24 18:41
(Received via mailing list)
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/
Posted by Davide Barison (Guest)
on 2013-01-24 18:43
Attachment: signature.asc (299 Bytes)
(Received via mailing list)
Mysql-server 5.1.66
Adapeter: mysql2 (0.3.11)

Il 24/01/13 18:40, David Welton ha scritto:
Posted by Fabrizio Regini (freegenie)
on 2013-01-24 18:44
(Received via mailing list)
Giusto, la versione di Mysql  importante. E anche la versione di Ruby, 
purtroppo
Posted by Davide Barison (Guest)
on 2013-01-24 18:54
Attachment: signature.asc (299 Bytes)
(Received via mailing list)
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:
Posted by Fabrizio Regini (freegenie)
on 2013-01-24 18:55
(Received via mailing list)
E la versione del server Mysql?
Posted by Davide Barison (Guest)
on 2013-01-24 19:02
Attachment: signature.asc (299 Bytes)
(Received via mailing list)
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:
Posted by Davide Barison (Guest)
on 2013-01-24 19:13
Attachment: signature.asc (299 Bytes)
(Received via mailing list)
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:
Posted by Fabrizio Regini (freegenie)
on 2013-01-24 21:45
(Received via mailing list)
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
Posted by David Welton (Guest)
on 2013-01-24 21:45
(Received via mailing list)
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/
Posted by Pietro Giorgianni (giorgian)
on 2013-01-24 22:40
(Received via mailing list)
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
Posted by Davide Barison (Guest)
on 2013-01-24 22:48
Attachment: signature.asc (299 Bytes)
(Received via mailing list)
Yes innodb

Il 24/01/13 21:45, David Welton ha scritto:
Posted by Davide Barison (Guest)
on 2013-01-24 22:50
Attachment: signature.asc (299 Bytes)
(Received via mailing list)
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:
Posted by gabriele renzi (Guest)
on 2013-01-25 09:48
(Received via mailing list)
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
Posted by Luca Mearelli (Guest)
on 2013-01-25 10:08
(Received via mailing list)
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
Posted by Pietro Giorgianni (giorgian)
on 2013-01-25 10:30
(Received via mailing list)
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
Posted by gabriele renzi (Guest)
on 2013-01-25 11:41
(Received via mailing list)
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
Posted by Matteo Collina (Guest)
on 2013-01-25 13:51
(Received via mailing list)
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
Posted by Sergio Berisso (Guest)
on 2013-01-25 14:02
(Received via mailing list)
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
Posted by Pietro Giorgianni (giorgian)
on 2013-01-25 14:16
(Received via mailing list)
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
Posted by Andrea Pavoni (apeacox)
on 2013-01-25 14:41
(Received via mailing list)
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
Posted by Davide Barison (Guest)
on 2013-01-25 15:56
Attachment: signature.asc (299 Bytes)
(Received via mailing list)
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
No account? Register here.