IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Procédural MySQL Discussion :

Générer ou vérifier code unique


Sujet :

SQL Procédural MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mars 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 21
    Par défaut Générer ou vérifier code unique
    Bonjour a tous,

    J'utilise mysql innodb pour une application. Je debute avec mysql (avec les bases de donnees en general). Voici mon probleme:

    J'ai deux connections independantes (dans des threads/processus differents) qui veulent rajouter une ligne dans une table. Pour rajouter une ligne, je dois au prealable generer un id unique sous forme de chaine de caracteres.

    Avant de faire mon INSERT, je fais un select pour chercher un ID unique. Le problement est que si les 2 threads tentent de creer une nouvelle ligne en meme temps, j'ai un risque de creation du meme ID. Pour cela, je pense que je dois locker la table entiere avant de chercher le nouvel ID. Et je delock la table apres le INSERT.

    Est-ce la bonne facon de faire?

    Merci d'avance,

    madric

  2. #2
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 815
    Billets dans le blog
    14
    Par défaut
    Si ton "id unique sous forme de chaine de caracteres" est la clé primaire de la table, c'est un mauvais choix !

    Si c'est une clé alternative, significative pour le domaine (une référence, un code, un numéro de série structuré...), alors utilise un TRIGGER BEFORE INSERT. Ainsi, la transaction est maître de la table pour déterminer le code alphanumérique à créer et à intégrer dans la requête INSERT.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Membre averti
    Inscrit en
    Mars 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 21
    Par défaut
    Merci pour ta reponse.

    Je vais regarder le TRIGGER_BEFORE.
    C'est effectivement une clef alternative.

    J'utilise le driver ODBC pour mysql. J'utilise des transactions et je lis dans la documentation que LOCK TABLES n'est pas compatibles avec les transactions et que son utilisation principale est justement l'emulation de transactions. En quoi les transactions peuvent permettre de se passer des locks de tables? Je peux avoir deux transactions concurrentes.

  4. #4
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 815
    Billets dans le blog
    14
    Par défaut
    Tu vas soumettre une requête INSERT.
    Le SGBD bloque la table pour traiter la requête.
    Il remarque qu'il y a un TRIGGER BEFORE INSERT sur cette table et l'exécute, ce qui permet de calculer en toute sécurité la clé alternative à insérer tant que la table est bloquée pour cette transaction.
    Une fois l'insertion effectuée, le SGBD libère la table pour l'autre processus qui patientait à la porte en se rongeant les ongles !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Membre averti
    Inscrit en
    Mars 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 21
    Par défaut
    C'est realisable en passant avec le driver ODBC?

  6. #6
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 815
    Billets dans le blog
    14
    Par défaut
    Je pense que oui puisque tout se passe dans le serveur MySQL. ODBC ne fait que transmettre la requête et attendre le résultat. C'est comme une insertion normale sauf que le SGBD fait un boulot en plus qu'une simple insertion.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  7. #7
    Membre averti
    Inscrit en
    Mars 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 21
    Par défaut
    ok, je vais essayer d'expliquer plus clairement ce que je veux faire.

    J'ai une table "PREFERENCES" qui a une clef primaire de type INTEGER en auto incrementation. Ensuite, les preferences sont rattachees a un utilisateur, j'ai une clef etrangere de type INTEGER qui y correspond. Ensuite, j'ai besoin d'un ID pour la preference, sous forme de chaine de caractere. Je veux que cet ID soit unique pour un utilisateur (un meme ID peut-etre utilise si les utilisateurs sont differents -> cle etrangere differente).

    Ce que je fais, surement pas terrible mais en gros:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    START TRANSACTION
    int index = 1; 
    string id;
    while (1) {
          id = "PREF%index"; (PREF1, PREF2, PREF3...)
          SELECT COUNT(ID) AS RESULT FROM PREFERENCES WHERE ID=id AND USERSEQ = x;
          if (result == 0) break;
          index++;
    }
     
    INSERT INTO PREFERENCES ID=id USERSEQ=x
    COMMIT TRANSACTION
    Voila, j'espere que c'est assez clair.
    Je veux pouvoir etre sur que mon id soit unique. Si 2 threads executent ce bout de code en meme temps, je peux me retrouver avec un id identique.

    L'idee avec le trigger serait alors ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    START TRANSACTION
    int index = 1; 
    string id;
    while (1) {
          id = "PREF%index"; (PREF1, PREF2, PREF3...)
          if (INSERT INTO PREFERENCES ID=id USERSEQ=x) == SUCESS) break;
          index++;
    }
    COMMIT TRANSACTION
    A moins que je ne me trompe completement, c'est comme ca que je voyais les choses.

  8. #8
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 815
    Billets dans le blog
    14
    Par défaut
    Si j'ai bien compris, tu veux que le couple {identifiant_utilisateur, id_preference} soit unique ?

    La table "PREFERENCES" est-elle issue d'une association du MCD ? Autrement dit, est-ce une table associative ?
    Si oui : fais du couple la clé primaire de la table.
    Si non : ajoute simplement un index unique sur le couple de colonnes.

    On peut avoir la structure de la table "PREFERENCES" et la description de l'association entre utilisateur et préférence ?

    Quelques billets à lire :
    - pour bien écrire les règles de gestion des données ;
    - pour savoir s'il faut faire une table associative et comment la faire.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  9. #9
    Membre averti
    Inscrit en
    Mars 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 21
    Par défaut
    Je ne sais pas ce qu'est une table associative. Je vais lire tes liens.

    Le truc en plus, c'est que l'ID peut-etre propose par le client, je ne peux donc pas me satisfaire d'une generation automatique.
    Dans les deux propositions que tu me fais, il me semble que ca assure que la bdd refusera la creation d'un couple (user,id) si il existe deja. Mon probleme se trouve en amont, au niveau de la creation de l'id. A moins que tu veuilles me dire qu'il suffit de laisser la bdd le soin de tester ca a ma place. Ce qui reviendrait a un truc du syle:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    START TRANSACTION
    int INDEX = 1; 
    string id;
    while (1) {
          id = "PREF%index"; (PREF1, PREF2, PREF3...)
          IF (INSERT INTO PREFERENCES ID=id USERSEQ=x) == SUCESS) break;
          INDEX++;
    }
    COMMIT TRANSACTION
    et donc la, pas besoin de trigger si je fais du couple (user,id) la clef primaire.

  10. #10
    Membre averti
    Inscrit en
    Mars 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 21
    Par défaut
    ok, j'ai compris ce qu'etait une table associative (enfin je crois).
    Ici, ce n'est pas le cas.

    Un utilisateur possede 0 a n preferences.
    Une preference n'est detenu que par un seul utilisateur.

  11. #11
    Membre averti
    Inscrit en
    Mars 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 21
    Par défaut
    bon, je viens de tester avec un index unique sur les deux champs et ca marche. Mais ca m'embete quand meme de rajouter un index. Ca ne risque pas de ralentir les insertions? Parce que la, ce nouvel index ne me sert que pour assurer l'unicite du couple (user, id). Le trigger me paraissait plus sympa, si il y avait moyen d'annuler l'insertion sous condition...

Discussions similaires

  1. Générer un code unique
    Par the watcher dans le forum Langage
    Réponses: 8
    Dernier message: 20/12/2009, 19h09
  2. Réponses: 1
    Dernier message: 17/04/2007, 13h07
  3. Executer une portion de code uniquement si le javascript est actif
    Par Rakken dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 07/04/2007, 10h23
  4. [Sécurité] Vérifier code crypté en md5
    Par vigon dans le forum Langage
    Réponses: 23
    Dernier message: 17/05/2006, 14h32
  5. [VBA-A]suivi d'un code unique d'un formulaire a un autre
    Par acidstrike dans le forum VBA Access
    Réponses: 4
    Dernier message: 09/03/2006, 15h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo