Raga help ci stiamo scervellando su questo problema

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

Che versione di Mysql e` con quale engine? Mi viene sempre il
sospetto…

Flame wars: meglio Postgresql:-)

2013/1/24 Davide B. [email protected]:

Se qualcuno di voi ha tempo da perdere qualsiasi aiuto e` il benvenuto.


Ml mailing list
[email protected]
http://lists.ruby-it.org/mailman/listinfo/ml


David N. Welton

http://www.welton.it/davidw/

http://www.dedasys.com/

Mysql-server 5.1.66
Adapeter: mysql2 (0.3.11)

Il 24/01/13 18:40, David W. ha scritto:

Giusto, la versione di Mysql importante. E anche la versione di Ruby,
purtroppo

Ruby 1.9 and Rails 3.2.11
Per la precisione stiamo usando ruby 1.9.3p125

Il 24/01/13 18:43, Fabrizio R. ha scritto:

E la versione del server Mysql?

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 B. ha scritto:

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 R. ha scritto:

Problemi con il fallimento dei validate uniqueness I me ne ricordo da
parecchio tempo.
Ed infatti:

Devi sempre mettere un indice unico a livello di database se vuoi stare
sicuro.

-f

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 B. [email protected]:

Ciao Raga grazie

David N. Welton
Twitter http://twitter.com/davidebarison Facebook


David N. Welton

http://www.welton.it/davidw/

http://www.dedasys.com/

Ciao,

Il 24 gennaio 2013 19:12, Davide B. [email protected] 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 [email protected]; 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
[email protected], 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

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 G. ha scritto:

Yes innodb

Il 24/01/13 21:45, David W. ha scritto:

2013/1/24 Pietro G. [email protected]:

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

2013/1/25 gabriele renzi [email protected]

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

2013/1/25 Pietro G. [email protected]:

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 :slight_smile:

  1. 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

Il 25 gennaio 2013 09:47, gabriele renzi [email protected] 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

Il giorno 25 gennaio 2013 13:50, Matteo C.
[email protected]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 :wink:

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 :slight_smile:
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 :slight_smile:

Ciao,
Sergio

Il 25 gennaio 2013 14:02, Sergio B. [email protected] 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 :slight_smile:
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 :slight_smile:

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

Il giorno 25/gen/2013, alle ore 14:15, Pietro G.
[email protected] 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”

:stuck_out_tongue:

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”.

:smiley:


http://andreapavoni.com