Probleme de duplication d'enregistrement , gem mysql?

Bonjour,

Je viens de transférer un site vers un nouveau serveur.

Sur ce serveur certaines données, comme les comptes utilisateurs, sont
dupliquées lors de l’enregistrement.

Les enregistrement sont effectuées à la même seconde à chaque fois, sur
des modele qui ont des regles de validation d’unicité sur certains
enregistrements.
(validates_uniqueness_of :email , :on => :create)

J’ai pu voir qu’il n’y avait pas la gem mysql d’installée, est ce qu’il
est possible que le problème vienne de là ?

Merci de votre aide

Le 21 septembre 2008 23:23, Frioffol F.
[email protected]a écrit :

enregistrements.
(validates_uniqueness_of :email , :on => :create)

J’ai pu voir qu’il n’y avait pas la gem mysql d’installée, est ce qu’il
est possible que le problème vienne de là ?

il me semble que si la gem mysql n’est pas installée , tu n’as pas de
connexion à ta base donc l’application ne fonctionne pas.

donc a priori non.

NG

2008/9/22 Nicolas G [email protected]:

dupliquées lors de l’enregistrement.
connexion à ta base donc l’application ne fonctionne pas.

donc a priori non.

rails fournis un connecteur mysql en ruby si jamais aucune autre gem
n’est installée. J’ai par le passé eu quelques problèmes avec des
serveurs n’ayant pas cette gem vu qu’elle n’est ni performante ni
fiable.

Il est possible que ca vienne de là bien que ce problème ne me
rappelle rien, mais pour t’en assurer compile la gem et refait le même
test.

http://fabien.jakimowicz.com

Bonjour,

Bonjour,

Attenton validate_uniqueness n’est pas garantie absolue d’unicité car
ton opération n’est pas atomique

En effet le pattern:

Requête 1: Test uniqueness => OK
Requête 2: Test uniqueness => OK
Requête 1: Insert user
Requête 2: Insert user => duplication du user

Est tout à fait possible, le seul moyen fiable de garantir l’unicité
c’est de gérer la contrainte au niveau de la base de donnée.

Ce genre de pattern d’erreur est plus probable d’arriver si ta
création de user se fait en ajax sans invalidé le bouton de submit et
que cette requête est particulièrement lente (FULL SCAN ?) car dans ce
cas là tes utilisateurs seront plus prompt à cliquer 2 fois sur submit
et comme tes requêtes sont lente le cas décrit est plus succeptible
d’arriver.

Un cas qui pourrait avoir tendance à empirer le nombre d’occurrence de
ce pattern est l’utilisation de table innodb avec des transactions. Le
commit ne se faisant qu’à la fin et si je ne m’abuse comme il n’y a
pas de table locking mais du row locking, si une 2ème requete arrive
en demandant la création du user tu es marron car comme ce n’est pas
commit le test d’unicité passe. A vérifier, j’utilise surtout du
myisam donc je dis peut-être des innepties.

J’ai pu voir qu’il n’y avait pas la gem mysql d’installée, est ce qu’il
est possible que le problème vienne de là ?

il me semble que si la gem mysql n’est pas installée , tu n’as pas de
connexion à ta base donc l’application ne fonctionne pas.

donc a priori non.

Faux, jusqu’à Rails 2.1.x tu as un connecteur bundle avec Rails. Il
est moins performant mais n’est pas buggé à ce point
là.A partir de Rails 2.2, sans gem mysql ca plantera par contre.

Renaud

2008/9/22 Renaud (Nel) Morvan [email protected]:

Requête 1: Test uniqueness => OK
Requête 2: Test uniqueness => OK
Requête 1: Insert user
Requête 2: Insert user => duplication du user

Est tout à fait possible, le seul moyen fiable de garantir l’unicité
c’est de gérer la contrainte au niveau de la base de donnée.

Es-tu sur que cela se produit avec l’utilisation que rails fait des
transactions SQL ?

Cela me surprend beaucoup.

http://fabien.jakimowicz.com

Est tout à fait possible, le seul moyen fiable de garantir l’unicité
c’est de gérer la contrainte au niveau de la base de donnée.

Es-tu sur que cela se produit avec l’utilisation que rails fait des
transactions SQL ?

Tu as raison de douter, mais il n’y a rien de plus simple à
vérifier :slight_smile:

  1. Myisam ne supporte pas les transaction, donc à moins d’utiliser les
    hooks mysql (procédure, intégrité, ON DUPLICATE …) ou de locker la
    table tu n’as pas de garantie que 2 requetes distinctes soient
    executées de facon atomiques
  2. Innodb supporte les transactions mais ne garantie absoluement pas
    le coté atomique de plusieurs transaction distinces exemple:

Si on prend l’exemple d’une table innodb users avec un champ email

client mysql1:
$ mysql -u root database
mysql> START TRANSACTION;
Query OK, 0 rows affected (0,00 sec)
mysql> select * from users where email=‘[email protected]’;
Empty set (0,00 sec)
mysql> INSERT INTO users set email= ‘[email protected]’;
Query OK, 1 row affected (0,08 sec)
select * from users where email=‘[email protected]’;
±-------------------+
| email |
±-------------------+
| [email protected] |
±-------------------+
1 row in set (0,00 sec)

client mysql2:
mysql> START TRANSACTION;
Query OK, 0 rows affected (0,00 sec)
mysql> select * from users where email=‘[email protected]’;
Empty set (0,00 sec)
mysql> INSERT INTO users set email= ‘[email protected]’;
Query OK, 1 row affected (0,08 sec)
select * from users where email=‘[email protected]’;
±-------------------+
| email |
±-------------------+
| [email protected] |
±-------------------+
COMMIT;
Query OK, 0 rows affected (0,00 sec)

client mysql1:
COMMIT;
Query OK, 0 rows affected (0,00 sec)
select * from users where email=‘[email protected]’;
±-------------------+
| email |
±-------------------+
| [email protected] |
±-------------------+
| [email protected] |
±-------------------+
2 rows in set (0,00 sec)

Boom :slight_smile:
Les transactions ici empire le problème car allonge le temps où
la
base de donnée ne possède pas le users avec l’email toto alors que
pourtant il va être committé

Ce n’est pas un problème de RAILS c’est juste une impossibilité de
gérer coté soft des contraintes niveau DB, ceci dit c’est “good enough
la plupart du temps” sauf si tu as des requêtes qui prennent des
plombes à commiter.

Renaud

2008/9/22 Renaud (Nel) Morvan [email protected]:

vérifier :slight_smile:
client mysql1:
±-------------------+
Query OK, 1 row affected (0,08 sec)
COMMIT;

Boom :slight_smile:
Les transactions ici empire le problème car allonge le temps où la
base de donnée ne possède pas le users avec l’email toto alors que
pourtant il va être committé

Ce n’est pas un problème de RAILS c’est juste une impossibilité de
gérer coté soft des contraintes niveau DB, ceci dit c’est “good enough
la plupart du temps” sauf si tu as des requêtes qui prennent des
plombes à commiter.

autant pour moi, j’ai pris l’habitude de ne bosser qu’avec postgres
qui n’a pas du tout ce comportement et qui justement passe
correctement ce test.

Sauf si j’ai mal effectué le test :wink:

http://fabien.jakimowicz.com

Sauf si j’ai mal effectué le test :wink:

En effet, j’ai mal fait le test et théoriquement toute base sql aura
ce comportement.

Ca existe et ca s’appelle “predicate locking” mais dans ce genre de
cas trivial pour éviter d’utiliser le LOCK, les procédures ou les
contraintes d’intégrité c’est jeter l’argent par les fenetres :slight_smile:

Globalement c’est ni sur postgres, ni sur mysql, mais ca doit se
trouver sur DB2 ou Oracle.

Bref il faut avoir en tête les limites des validations cross records a
la Rails, en particulier en mode full transactionnel avec des after
_create gourmant.

Renaud

2008/9/22 Fabien J. [email protected]:

Tu as raison de douter, mais il n’y a rien de plus simple Ã

| email |
mysql> INSERT INTO users set email= ‘[email protected]’;
client mysql1:
2 rows in set (0,00 sec)

autant pour moi, j’ai pris l’habitude de ne bosser qu’avec postgres
qui n’a pas du tout ce comportement et qui justement passe
correctement ce test.

Sauf si j’ai mal effectué le test :wink:

En effet, j’ai mal fait le test et théoriquement toute base sql aura
ce comportement.


http://fabien.jakimowicz.com

Renaud (Nel) Morvan wrote:

Sauf si j’ai mal effectu� le test :wink:

En effet, j’ai mal fait le test et th�oriquement toute base sql aura
ce comportement.

Ca existe et ca s’appelle “predicate locking” mais dans ce genre de
cas trivial pour �viter d’utiliser le LOCK, les proc�dures ou les
contraintes d’int�grit� c’est jeter l’argent par les fenetres :slight_smile:

Globalement c’est ni sur postgres, ni sur mysql, mais ca doit se
trouver sur DB2 ou Oracle.

Bref il faut avoir en t�te les limites des validations cross records a
la Rails, en particulier en mode full transactionnel avec des after
_create gourmant.

Renaud

Salut ,

Merci pour vos infos et désolé de ma réponse tardive je n’ai pas pu me
connecter depuis mon premier message.

Avant d’essayer d’installer cette gem j’ai utilisé le masquage du bouton
submit pour voir si une double soumission de formulaire pouvait être la
cause du problème mais ça ne change absolument rien.
J’ai toujours des inscriptions utilisateurs en doublons de manière
occasionnelle.

Au niveau de la gem mysql je me demandais si il etait possible de
l’installer sur ce serveur sans avoir d’interuption de service ?
J’ai posé la question à mon hébergeur qui refuse de faire l’installation
sur un serveur en production…(site e-commerce)

Je me sens un peu coincé là n’ayant pas de grande connaissances en
systeme.

Merci !

Le 22 septembre 2008 12:11, Renaud a écrit :

Est tout à fait possible, le seul moyen fiable de garantir l’unicité
c’est de gérer la contrainte au niveau de la base de donnée.
(…)

Pour compléter les dires de Renaud, lire la doc (dans Edge
mais pas dans 2.1)

– Jean-François.


Les 50 ans du Lisp : http://www.lisp50.org
http://twitter.com/underflow_