ALAHYANE Rachid a écrit, le 05/07/2009 11:00 PM :
> Le problème avec mon application, c'est que la saisie se fait via un
> formulaire généré à la volé (du javascript)
>
>
Le problème avec une application web c'est qu'il peut y avoir plusieurs
requêtes simultanées. Ton cas n'est donc pas exceptionnel. Le
validates_uniqueness_of ne protège pas contre deux requêtes simultanée
ayant pour effet de créer des entrées conflictuelles puisqu'il se
contente de vérifier si une entrée conflictuelle existe *avant* de
l'ajouter.
Comme l'expliquait Fabien, la seule solution est d'ajouter la contrainte
d'unicité en base.
Une autre consisterait à créer une transaction et verrouiller la table
entière avant d'essayer de sauver l'objet, mais d'une part les
performances baisseraient beaucoup et d'autre part il serait très facile
de se retrouver en situation de deadlock.
> Je passe par de tas de partiels pour afficher ce formulaire...
>
> Je me suis dis que ce peut être ActiveRecord insère les deux lignes en
> une seule requête, mais lorsque j'ai consulté les logs j'ai trouvé que
> ce n'est pas le cas. C'est atomique, voici un bout de log :
>
> SQL (0.4ms) INSERT INTO "properties" ("name", "updated_at",
> "version_id", "value", "created_at") VALUES(E'req2', '2009-05-06
> 18:23:49.090473', 3, E'hgjhg', '2009-05-06 18:23:49.090473') RETURNING
> "id"
>
> SQL (0.4ms) INSERT INTO "properties" ("name", "updated_at",
> "version_id", "value", "created_at") VALUES(E'req2', '2009-05-06
> 18:23:49.096753', 3, E'lkj', '2009-05-06 18:23:49.096753') RETURNING "id"
>
> SQL (0.4ms) INSERT INTO "properties" ("name", "updated_at",
> "version_id", "value", "created_at") VALUES(E'req2', '2009-05-06
> 18:23:49.098239', 3, E'kjlkj', '2009-05-06 18:23:49.098239') RETURNING
> "id"
>
> SQL (0.4ms) INSERT INTO "properties" ("name", "updated_at",
> "version_id", "value", "created_at") VALUES(E'req2', '2009-05-06
> 18:23:49.099697', 3, E'sdfasdf', '2009-05-06 18:23:49.099697')
> RETURNING "id"
>
Note que ces requêtes sont séparées par quelques millisecondes au plus :
le SELECT fait par le processus qui génère le dernier INSERT pour
vérifier qu'il n'y a pas de conflit a déjà eu lieu lorsque le premier
INSERT s'exécute (ce que tu peux aisément vérifier dans tes logs) et ne
voit donc pas de problème.
>
> cela ne vient pas du fait que j'utilise du javascript ?
Non, ça vient du fait qu'il n'y a pas moyen de vérifier qu'un autre
processus ne fait pas quelquechose derrière ton dos dans la base de
données si tu ne demandes pas à la base de données de le vérifier pour
toi (en ajoutant les contraintes qui te sont nécessaires dans cette
dernière). Les requêtes faites en Javascript illustrent juste le
problème (qui se produirait de toute façon lorsque plusieurs
utilisateurs accèderaient à ton appli pour créer des entrées
conflictuelles).
Lionel
--~--~---------~--~----~------------~-------~--~----~
Vous avez reçu ce message, car vous êtes abonné au groupe "Railsfrance" de
Google Groups.
Pour transmettre des messages à ce groupe, envoyez un e-mail à l'adresse
[email protected]
Pour résilier votre abonnement envoyez un e-mail à l'adresse
[email protected]
-~----------~----~----~----~------~----~------~--~---