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

JDBC Java Discussion :

accès multi thread


Sujet :

JDBC Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de r2d2abc
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 212
    Par défaut accès multi thread
    Avant toute chose, bonne année à tous.

    J'ai un soucis depuis 3 semaines qui ressort sur une appli qui tourne depuis un an sans soucis, donc sans idées sur le pourquoi je vous le soumets.

    Symptomes:
    Depuis 3 semaines j'ai eu 3 crash d'index et une perte totale d'un fichier de données. Si j'avais un petit doute au début (après des mois de traitements sans incidents) je n'en ai plus, il y a un soucis qqpart.

    contexte :
    Une application sous java en multi thread qui utilise 2 tables MYSQL (5.0.27).
    Les tables sont super simples avec une dizaine de colonnes chacune.
    Chaque table a une classe dédiée métier qui s'occupe des requêtes.
    Des transactions arrivent par socket d'un système externe.
    Pour chacune d'elle un thread qui s'occupe d'effectuer un traitement approprié avec accès sur 2 tables (création/modification/..) est lancé.
    Plusieurs thread de traitement peuvent être lancés en même temps (si plusieurs transactions entrantes).
    Chaque thread de traitement instancie les 2 classes d'accès aux tables.
    Tout (semble) bien parallèle, bien protégé.
    Il y a une variable connection (jdbc) en globale static pour toute l'application initialisée dès le début.
    Cette connection est passée à chaque nouvelle instance de classe d'accès aux tables créée par les threads de traitement.
    Code :

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     
    //skeleton COLUMN access TABLE
    public DBTx implements K
    {
      private Connection          cx          = NULL;
      private Statement           stm        = NULL;
     
      public DBTx (Connection connection) throws SQLException
      {
        cx = connection;
        IF (cx != NULL)
          stm = cx.createStatement();
      }
     
     String Get (String KEY)
     {
       Resultset rs=NULL
       String value="",query="";
       try
       {
          query="...";
          rs = stm.executeQuery(query);
          //traitement du rs ..
       }
       catch (SQLException e)
       {
       }
       finally
       {
         rs.close();
       }
       RETURN value;
     }
     
     String Process (String KEY)
     {
       Resultset rs=NULL
       String value="",query="";
       try
       {
          query="...";
          rs = stm.executeQuery(query);
          //traitement du rs ..
          ...
       }
       catch (SQLException e)
       {
       }
       finally
       {
         rs.close();
       }
       RETURN value;
     }
     
     BOOLEAN UPDATE (String KEY, String DATA[])
     {
       String query="";
       BOOLEAN ok=false;
       try
       {
          query="...";
          stm.executeUpdate(query, Statement.RETURN_GENERATED_KEYS); 
          ...
          ok=true;
       }
       catch (SQLException e)
       {
       }
       finally
       {
       }
       RETURN ok;
     }

    Chaque classe instanciée a en global une variable statement et en local à chaque méthode un resultset qui est fermé à la fin de chaque méthode.

    Le statement doit il être local à chaque méthode (ds le cas où 2 méthodes de la même classe sont appelées en même temps) ?
    Doit il être clôturé obligatoirement ?
    Comme c le driver qui gère les accès simultanés en lecture/création, seuls les update devraient être managés par des synchronized ou lock donc normalement quid des telescopages donc je suis dans le noir.

    Merci de votre aide et suggestion à tous.

  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
    Citation Envoyé par r2d2abc Voir le message
    Tout (semble) bien parallèle, bien protégé.
    Il y a une variable connection (jdbc) en globale static pour toute l'application initialisée dès le début.
    chaque thread doit avoir sa propre connection à la base de donnée. L'objet connection de jdbc n'étant pas ThreadSafe. Il en va ainsi de même pour tous les objets découlant de la connection (Statement, resultset, transaction....).

  3. #3
    Membre confirmé Avatar de r2d2abc
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 212
    Par défaut
    Salut et merci de ta réponse.

    Cela veut dire que pour un thread dont la durée de vie est de quelques ms je dois faire un DriverManager.getConnection(url) .. que tous les statements seront locaux à chaque méthode des classes .. ?
    c un pas un peu lourd ? je pensais que le niveau connection pouvait être le canal réutilisable de tous les statements..
    c pas très optimal non ? je peux avoir plusieurs (dizaines) de milliers de transactions par jour à traiter on peut pas mutualiser un peu les traitements et éviter une surcharge en déclarations ?

    thank's

  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
    la connection, ce n'est pas threadsafe, point. Maintenant tu as plusieurs possiilités au choix

    1) avoir un certains nombre de threads pour traiter tes demandes extérieures, ces thread auront chacun leur connection avec des statements préparés. Dans ce cas, t'as juste à réutiliser les Thread au lieu de les arreter. Ainsi ton application gardera, par exemple, une dixaine de connections en continu. Ce cas me semble intéressant dans ton cas car, non seulement on évitera de créer à chaque fois une connection, mais en plus on évitera de créer à chaque fois un thread, ce qui est aussi un processus lourd Le tout est de calibrer après la taille de ton pool de threads.

    2) utiliser un connection pool. Dans ce deuxième cas, tu crée pour chaque demande entrante un nouveau thread qui va aller demander une connection au pool. C'est ce dernier qui se chargera d'éviter de créer / fermer en continu des connections mais plutot de les réutiliser de manière propre.


    3) continuer a utiliser une seule connection, mais dans ce cas, utiliser des blocs synchronized autour de toutes tes transactions pour éviter les conflits -> solution qui va vite plomber tes performances, je pense...

  5. #5
    Membre confirmé Avatar de r2d2abc
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 212
    Par défaut
    bon alors changement relativement profond de structure -> pas neutre (et surtout grosse erreur initiale) il va falloir faire attention car cette appli qui tourne en prod.
    je vais voir entre les 1° & 2° solution la plus optimale & la moins couteuse en terme de dev.
    Sur la question de déclarer un statement en global à la classe plutôt que local à chaque procédure je pense donc que tu es aussi pour la déclaration systématique en local non de chaque méthode non ?
    merci tchize

  6. #6
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Je ne suis pas tout à fait du même avis que tchize_, pour moi, en fonction du traitement à faire, on peut très bien partager l'objet Connection.
    Il n'en va pas de même avec l'objet Statement !
    Le plus sûr serait de mettre le traitement dans un bloc try catch finally et dans cette dernière, placer la fermeture du statement et du resultSet tant qu'à être propre (bien que la fermeture du statement entraine la fermeture du resultset)
    Les blocs de synchronisation sont gourmands en ressource système (surtout avec Windows) donc, si ce n'est pas utile, autant l'éviter.

    A toi de voir
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    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
    Citation Envoyé par OButterlin Voir le message
    Je ne suis pas tout à fait du même avis que tchize_, pour moi, en fonction du traitement à faire, on peut très bien partager l'objet Connection.
    C'est ce que j'ai dit (cf deuxième post), mais la connection n'est pas threadsafe, il faut donc utiliser des bloc synchronized pour éviter les clash. Si on pouvais utiliser une connection jdbc depuis plusieurs threads sans synchronized, on s'emmerderait pas à faire des connection pool pour les webapp, on ferait une seule connection que tout le monde utiliserait. Et dans son cas, je pense, les blocs synchronized risquent de tuer ses performances.

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

Discussions similaires

  1. Multi thread accès variable
    Par untipy dans le forum Embarqué
    Réponses: 5
    Dernier message: 24/03/2015, 08h09
  2. [Multi-thread] Comment lock l'acces a un containeur de la STL ?
    Par Izidor's dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 14/10/2009, 12h09
  3. [EF] Accès multi thread
    Par dev01 dans le forum Accès aux données
    Réponses: 27
    Dernier message: 27/03/2009, 15h08
  4. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  5. [Kylix] exception qtinft.dll et multi-threading
    Par leclaudio25 dans le forum EDI
    Réponses: 3
    Dernier message: 27/03/2003, 18h09

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