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

Java Discussion :

Implémenter un lock au niveau de la base de données


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de rt15
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2005
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 262
    Par défaut Implémenter un lock au niveau de la base de données
    Salut,

    Je travaille sur un programme pouvant tourner sur n machines mais travaillant sur la même base (Disons une MySQL ou une Oracle).
    Mais il faut que je sois sûr que certaines opération ne soient réalisées que par un seul programme en même temps.
    Donc il me faudrait un genre de lock/mutex/semaphore, bref un truc qui permette de m'assurer qu'un seul de mes programmes fait un truc précis à ce moment là.
    Attention, une "infinité" de type d'opération doit être permise, et on ne les connait pas toutes à l'avance.
    Il y a aussi une potentielle "infinité" de programme et ils n'ont pas d'identifiant.
    De plus il faut absolument éviter les deadlocks en cas de crash de l'application.
    Le mécanisme "programme qui tombe" -> "connection qui tombe" -> "lock qui tombe" semble donc être la seule solution. D'où l'utilisation d'un "select for update".
    Le niveau d'isolation de transaction est fixé à TRANSACTION_READ_COMMITTED.

    Je cherche à pouvoir faire ce genre de code :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DatabaseLock lock = lockManager.createLock("Operation A");
    lockManager.lock(lock);
    try
    {
      // Je suis sûr qu'un seul de mes programme peut être ici à un instant t.
    }
    finally
    {
      lockManager.unlock(lock);
    }

    Ma solution actuelle ressemble au code suivant (Code à la main histoire d'avoir une vague idée, manque des traitements d'erreurs...), avec une table lock_table disposant d'une colonne name avec une clé primaire dessus :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    public class LockManager
    {
    public DatabaseLock createLock(String name)
    {
      return new DatabaseLock(name);
    }
     
    public void lock(DatabaseLock lock)
    {
      Connection connection = new Connection();
      try
      {
        connection.execute("insert into lock_table values (" + lock.getName() + ")");*
      }
      catch (SQLException e)
      {
         // Si l'exception est une duplication de clé primaire, on ignore.
      }
      connection.commit();
     
      // A ce stade, devrait y avoir une ligne. On fait un select for update dessus.
      connection.execute("select name from lock_table where name = " + lock.getName() + " for update");
      lock.setConnection(connection);
    }
     
    public void unlock(DatabaseLock lock)
    {
      Connection connection = lock.getConnection();
      connection.execute("delete from lock_table where name = " + lock.getName());
      // Libère le lock du select for update et supprime la ligne en même temps.
      connection.commit();
      connection.close();
    }
    }

    Dans les faits cela ne fonctionne pas assez bien.
    Par exemple, un premier programme peut insérer la ligne et la commiter. Un deuxième peut essayer de faire pareil, et utiliser la ligne du premier pour faire le select for update. Il va finalement supprimer la ligne alors que le premier thread va chercher à faire un select for update dessus.
    De plus avoir un select/delete et un insert de la même ligne dans des transactions différentes semble générer des problèmes de deadlock ou la base ne sait plus quelle transaction devrait avoir raison au final...

    Bref, c'est loin d'être stable et propre.

    Pourtant dans la théorie ce type d'algo (Lock au niveau de la base) semble super pratique et généraliste, mais je ne trouve pas de solution.

    Quelqu'un a des idées ?

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    d'abord pour isoler tes transaction, il vaut mieux préférer une isolation de type serializable dans ton cas, ca garanti que l'ordre de tes nobmreuses opération n'affectera pas le résultat.

    Pour les deadlock, il faut toujours prendre tes locks dans un ordre précis. Si la transaction 1 demande A puis B et que la transaction 2 demande B puis A, t'es dans une situation de deadlock potentiel.
    Si tu ne sais pas ordonner tes verrous, alors il est préférable de viser des gestionnaires de base de donnée détectant les deadlock et capable des les réparer en rollbackant une transaction.

    Enfin, personellement, je déteste les tables de verrous, ca m'a toujours l'air d'emplatre pour éviter de faire simplement correctement ses select et ses update Mettre volontairement des verrou, c'est brider volontairement une base de données là ou une transaction serializable peut à elle seule donner des garanties d'intégrité. Ou alors tu veux verrouiller dans la table pour faire des opération hors db (email, gestion de fichiers, que sais-je)

  3. #3
    Membre éclairé Avatar de rt15
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2005
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 262
    Par défaut
    Merci pour cette réponse. Effectivement c'est assez pénible à mettre en place et potentiellement source de gros problèmes... Mais dans notre cas, on a pas trop le choix, on ne fait pas que des insert/update.

    Je vais donc regarder du côté de TRANSACTION_SERIALIZABLE comme tu le propose.

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    tu peux donner un exemple de ce que vous faites d'autre?

  5. #5
    Membre éclairé Avatar de rt15
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2005
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 262
    Par défaut
    Surtout du create table, de l'alter table... Rien qui soit extérieur à la base de données genre fichiers ou mails.

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    create table / alter table, c'est du DDL, c'est hors transaction de toutes façon. Tes verrous ne servirons à rien. Par exemple, sous oracle, faire une opération DDL au milieu d'une transaction commite implicitement cette transaction avant le DDL et recommence une nouvelle transaction après. Donc tous tes verrous dans la DB vont être libérés.

    Et la doc de mysql mentionne aussi explicitement le même comportement.

Discussions similaires

  1. Pas de changments au niveau de la base de données
    Par daydream123 dans le forum Hibernate
    Réponses: 4
    Dernier message: 14/12/2012, 11h31
  2. Chargement des donnés au niveau d'une base de donnée Mysql
    Par srera dans le forum Développement de jobs
    Réponses: 1
    Dernier message: 29/11/2011, 16h33
  3. Réponses: 7
    Dernier message: 23/11/2011, 17h29
  4. [Wamp] Wampserver et Vista incompatible au niveau de la base de données
    Par donfino dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 7
    Dernier message: 24/05/2008, 16h09
  5. Mot de passe niveau base de donneé oublié
    Par simbonikala dans le forum Access
    Réponses: 2
    Dernier message: 19/01/2006, 12h45

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