2010-06-18 5 views
3

Je déteste soulever une question qui est largement demandé sur le web, mais je ne peux pas sembler le résoudre.MySql trop de connexions

J'ai commencé un projet il y a quelques temps et après un mois de tests, j'ai rencontré une erreur "Trop de connexions". J'ai regardé dedans, et "Résolu" en augmentant les connexions max. Cela a ensuite fonctionné.

Depuis lors de plus en plus de gens ont commencé à l'utiliser, et il a encore frappé. Quand je suis le seul utilisateur sur le site, je tape "show processlist" et il arrive avec environ 50 connexions qui sont toujours ouvertes (en disant "Sleep" dans la commande). Maintenant, je ne sais pas assez pour spéculer pourquoi ils sont ouverts, mais dans mon code je tripple vérifié et chaque connexion que j'ouvre, je ferme.

ie. Chaque fois que je fais autre chose sur le site, une autre charge de connexions est ouverte et non fermée. Y at-il un problème avec mon code? et sinon, quel pourrait être le problème?

+0

Que fait this.getSession(). Connection()? –

+0

Et est-ce le seul endroit dans votre application que vous ouvrez des connexions? –

+0

Enregistrez-vous toutes les exceptions quelque part? –

Répondre

0

Si le code déclenche une exception DataAccessException ou java.sql.SQLException, la connexion ne sera pas fermée, ce qui entraînera de nombreuses connexions inactives ouvertes;) Créez un bloc try-finally-block qui fermera la connexion.

Connection conn = this.getSession().connection(); 
try { 
    // all code 
} finally { 
    rs.close(); 
    smt.close(); 
    conn.close(); 
} 

Il est un exemple trivial, mais un peu plus complexe parce que vous devez vérifier Wich de ces objets sont vraiment créés et utilisés.

11

Avec votre approche, la connexion ne sera jamais fermée si une exception a été levée avant s'appelle conn.close(). Vous devez l'acquérir (ainsi que l'instruction et le jeu de résultats) dans un bloc try et le fermer dans le bloc finally. Tout code finallysera toujours exécuté, quelle que soit l'exception levée ou non. Avec cela, vous pouvez assurer que les ressources coûteuses seront fermées.

est ici une ré-écriture:

public int getSiteIdFromName(String name, String company) throws DataAccessException, java.sql.SQLException { 
    Connection conn = null; 
    Statement smt = null; 
    ResultSet rs = null; 
    int id = 0; 
    try { 
     conn = this.getSession().connection(); 
     smt = conn.createStatement(); 
     String query = "SELECT id FROM site WHERE name='" + name + "' and company_id='" + company + "'"; 
     rs = smt.executeQuery(query); 
     rs.next(); 
     id = rs.getInt("id"); 
    } finally { 
     if (rs != null) try { rs.close(); } catch (SQLException logOrIgnore) {} 
     if (smt != null) try { smt.close(); } catch (SQLException logOrIgnore) {} 
     if (conn != null) try { conn.close(); } catch (SQLException logOrIgnore) {} 
    } 
    return id; 
} 

Cela dit, ce code est sensible à SQL injectionattacks. Utilisez un PreparedStatement au lieu de Statement.

Voir aussi:

+1

Une autre réponse informative et descriptive BalusC, merci. Je vais faire un tour sur le site et voir si cela résout le problème – MichaelMcCabe

2

Un flux possible, dans lequel ce code peut fuir la connexion est:

  1. Stmt.executeQuery() Résultats vide
  2. resultset Vous ne vérifie pas si rs.next() retourne vrai ou faux
  3. rs.getInt ("id") émet une exception comme il est sauté

n'est pas rangée courante dans

  • resultset conn.close() Effectuez les opérations suivantes:

    1. Faire rs.getInt() conditionnelle à rs.next()
    2. Fermez la connexion en bloc finally et faire tout l'accès aux données dans le bloc try

    Edit:

    De même, il est recommandé d'enregistrer toutes les exceptions quelque part afin d'avoir un bon point de départ pour le dépannage.

  • 0

    La solution temporaire pour ce problème peut être d'augmenter les connexions maximales autorisées du mysql. Vous pouvez le faire par l'une des deux manières mentionnées ci-dessous.

    Première:

    Connectez-vous au serveur mysql et tapez la commande suivante donnée.

    mysql> SET GLOBAL max_connections = 200; 
    

    Cela augmentera le nombre maximum de connexions. Mais ce paramètre changera si le serveur est redémarré.

    Deuxième:

    Modifier le fichier /etc/mysql/my.cnf et d'augmenter le max_connection dans ce fichier.

    [mysqld] 
    local-infile=0 
    datadir=/var/lib/mysql 
    user=mysql 
    symbolic-links=0 
    
    max_connections = 100 
    

    Enregistrez les modifications et tapez la commande suivante pour redémarrer mysqld:

    /etc/init.d/mysqld restart 
    

    Mais ce problème, apparaît généralement à cause des connexions ouvertes qui ne sont pas fermer correctement et ne sont pas disponibles à utiliser. Essayez simplement d'examiner toutes les ressources qui accèdent à votre base de données et vérifiez si toutes les connexions sont correctement gérées.

    En regardant dans le code, on peut voir que vous n'avez pas placé le code dans le try and catch. Selon votre code, si l'exception se produit lors de l'extraction des données, votre connexion ne sera pas fermée et donc ce sera un gaspillage de ressources. D'où le standard de codage suggère d'utiliser le try and catch pour enfin gérer les connexions .

    try{ 
    //your code 
    } 
    catch(Exception e){ 
    
    //handle the exceptions here 
    } 
    
    finally{ 
         try{ 
          channel.close(); 
         } catch(Exception e){ 
          log.error("Error is "+e.getMessage(),e); 
          e.printStackTrace(); 
         } 
         try { 
          connection.close(); 
         } catch (IOException e) { 
          log.error("Error is "+e.getMessage(),e); 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
         catch(Exception e){ 
          log.error("Error is "+e.getMessage(),e); 
          e.printStackTrace(); 
         } 
        } 
    
    Questions connexes