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 :

Hard shutdown et fermeture de la connexion avec la base h2


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    174
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 174
    Par défaut Hard shutdown et fermeture de la connexion avec la base h2
    Bonjour à tous,
    Un problème a été constaté lorsqu'un hard shutdown (kill du process java) est fait sur le serveur d'une application java et je ne vois pas de solution évidente (ou alors je n'y ai pas pensé^^). Je viens donc vers vous pour y trouver une solution.

    Voici quelques explications:
    - L'application utilise une base H2 avec auto commit (qui n'est pas la dernière version donc il faudrait que je teste avec la dernière mais je pense qu'il y aura le même type de problème)
    - Lors du démarrage du serveur, un DataSource (JdbcConnectionPool dans mon cas pour h2) est créé
    - A la première demande de connexion pour l'exécution d'une requête (appel à getConnection() sur le DataSource), un appel à org.h2.engine.Database.openDatabase() est fait (ce qui créé un fichier ".lock.db" dans le répertoire de la base)
    - Lors de certaines requêtes d'insertion, une séquence est incrémentée dans la base h2 (car c'est un ID déclaré en AUTO_INCREMENT)
    - Toutes les connexions sont bien fermées suite à l'exécution de la ou des requêtes
    - Lors de l'arrêt normal du serveur, un appel à JdbcConnectionPool.dispose() est fait ce qui provoque un appel à org.h2.engine.Database.close() (le fichier ".lock.db" est supprimé dans le répertoire de la base)
    - Suite à un arrêt normal, la valeur des séquences est bien sauvegardée en base
    - Cependant, lors d'un hard shutdown, il n'y a pas d'appel ni à JdbcConnectionPool.dispose() ni à org.h2.engine.Database.close() ce qui fait que la valeur de la séquence n'est pas sauvegardée (elle semble être réinitialisée à sa valeur initiale) -> Cela provoque donc une incohérence entre la séquence et le dernier ID ajouté en base qui amène à une SQLException de violation de la clé primaire lors d'une tentative d'ajout

    Mon idée était de détecter une commande de kill et de fermer correctement la base si tel est le cas mais je ne sais pas si c'est possible? Sinon, avez-vous d'autres idées?

    Le but recherché est d'être robuste.

    Merci d'avance pour votre aide .

  2. #2
    Membre Expert
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Par défaut
    Tu peux regarder les ShutdownHook, normalement ça devrait te permettre de faire ça

    http://docs.oracle.com/javase/7/docs...g/Runtime.html

    Exemple de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Thread shutdownHook = new Thread( "myapp-shutdown-hook" )
        {
            public void run()
            {
                System.out.println( "Starting MyApp shutdown..." );
                // Do some cleanup work.
                System.out.println( "MyApp shutdown complete." );
            }
        };
    Runtime.getRuntime().addShutdownHook( shutdownHook );

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    174
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 174
    Par défaut
    Merci pour ton retour.

    J'ai essayé mais on ne passe pas dans le run() en cas de kill par le gestionaire des taches:

    Code : 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
     
    public class TestHardShutdown {
     
      public static void main(final String[] args) {
        System.out.println("Test hard shutdown start.");
     
        Runtime.getRuntime().addShutdownHook(new Thread() {
          @Override
          public void run() {
            System.out.println("Hard shutdown intercepted 1.");
          }
        });
     
        while (true) {
          System.out.println("Boucle.");
          try {
            Thread.sleep(1000);
          } catch (final InterruptedException iException) {
            // TODO Auto-generated catch block
            iException.printStackTrace();
          }
        }
     
      }
    }
    Y a t-il un moyen de ne pas perdre la valeur de la séquence dans h2 (cache dans h2 pour éviter que dans un tel cas la valeur de la séqunce ne soit perdue)?

    En fait il faudrait je pense plutot voir si dans h2 je ne peux pas configurer mieux pour éviter la perte de la valeur de la sequence. Quelqu'un connait-il un moyen?

  4. #4
    Membre Expert
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Par défaut
    Citation Envoyé par philou44300 Voir le message
    J'ai essayé mais on ne passe pas dans le run() en cas de kill par le gestionaire des taches
    Ha mais c'est normal ça, c'est l'OS qui donne l'ordre "crève tout de suite maintenant c'est un ordre" à un process ça !

    Lance ton programme en ligne de commande, puis fait un CTRL+C pour demander l'arrêt du process -> tu vas passer par le hook.
    Ca marche aussi si tu reçois un ordre de kill simple (pas un SIGKILL, ou un kill -9 sous linux), un signal SIGTERM, tous les threads qui sont terminés, le passage sur un System.exit(0), le PC qui s'arrête...

    Quand tu disais "hard shutdown", je ne pensais pas que tu parlais d'un kill immédiat du process ! (ce qui bien entendu dans ce cas là ne marchera pas)

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    174
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 174
    Par défaut
    Si c'est un kill immédiat^^ (c'est pour ca que je ne touve rien de concluant à faire en java). En fait, le client "coupe l'alimentation" (c'est donc pire qu'un kill même si au final cela correspond à la même chose) ce qui fait que le close() n'est pas fait avec la database (l'application est embarquée donc quand on tourne la clé paf tout s'arrête... de manière pas très propre donc).

    Je m'oriente donc plutot vers la base h2. Apparemment, les séquences créées pour l'AUTO_INCREMENT ont, d'après ce que j'ai compris de la doc, par défaut un cache de 32 valeurs (si j'insère 32 lignes, la séquence va être augmentée dans le cache et c'est seulement à la 33 ème insertion ou lors d'un close() que la valeur de la séquence va être persistée). Je vais donc essayer de créer une séquence sans cache (avec 0 comme taille de cache) et utiliser cette séquence plutot que AUTO_INCREMENT.

  6. #6
    Membre Expert
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Par défaut
    Citation Envoyé par philou44300 Voir le message
    En fait, le client "coupe l'alimentation" (c'est donc pire qu'un kill même si au final cela correspond à la même chose)


    J'ai bien une idée là tout de suite qui me vient à base d'onduleur qui envoie un signal, intercepté par un Listener sur le PC qui se charge de couper proprement les services, mais je pense que ça existe déjà et que ça se vend cher...


    Mais du coup, c'est clairement pas un problème que tu pourras résoudre en Java. Et dans tous les cas, il y a un risque de faire péter la structure de ta base aussi et de corrompre les données si c'est pas coupé au bon moment.

    Autre solution, tu éduques ton client et tu lui apprends à éteindre proprement un ordinateur...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 18/04/2010, 18h34
  2. [VB6]Problème connexion avec une base ACCESS
    Par mcay dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 15/05/2006, 17h47
  3. Réponses: 6
    Dernier message: 20/09/2005, 22h28
  4. problème de connexion avec une base firebird
    Par vbcasimir dans le forum Bases de données
    Réponses: 1
    Dernier message: 30/05/2005, 11h40
  5. [WSAD5] Connexion avec une base Lotus
    Par mickey dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 11/03/2004, 08h37

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