JDBC MySQL Problème de Connexion - Tentative de reconnexion 3 fois. Abandonner
J'ai un reste de l'application de service de l'exécution de l'Java framework Spring. L'application dépend d'un raccordement à une source externe de bases de données MySQL, qui est connecté via JDBC.
Mon problème est le maintien d'un lien solide entre le reste du service et de la db MySQL. J'ai ce que je considère un rudimentaire connexion failsafe en place qui ressemble à quelque chose comme:
public Connection getConnection() throws SQLException {
if(connection == null){
this.buildConnection();
}
else if(!connection.isValid(10)){ //Rebuild connection if it is no longer valid
connection.close();
this.buildConnection();
}
return connection;
}
À l'aide de cette méthode doit s'assurer que la connexion est valide avant toute requête est exécutée. Mon problème est que je périodiquement obtenez une exception lors de l'appel de cette méthode:
Ne pouvait pas créer une connexion au serveur de base de données. Tentative de reconnexion 3 fois. D'abandonner. SQLState: 08001. ErrorCode: 0.
Les choses qui m'ont super perplexe à ce sujet sont:
- Cette erreur ne se produit périodiquement. De nombreuses fois la connexion fonctionne tout simplement trouver.
- Je test cette même application sur mon ordinateur du développeur et cette erreur ne se produit jamais.
J'ai configuré la base MySQL sur mon propre serveur, donc je contrôle toutes ses options de configuration. À partir de cela, je sais que ce problème n'est pas lié au nombre maximum de connexions autorisées, ou un délai d'attente de connexion.
Édition - Mise À Jour 1:
- Ce service est hébergé dans le Cloud de Service sur la plateforme Azure de Microsoft.
- J'ai accidentellement mis en place comme un exemple dans le Nord de l'Europe, alors que la DB est situé en Amérique du Nord, probablement pas lié, mais en essayant de peindre l'ensemble de l'image.
- Essayé les conseils à ce lien, sans succès. Pas en utilisant des pools de threads, et tous les jeux de résultats et les Déclarations/PreparedStatements sont fermées après.
Édition - Mise À Jour 2
Après quelques refontes, j'ai été en mesure de mettre en œuvre avec succès un HikariCP Pool de Connexion comme indiqué par @M. Deinum ci-dessous. Malheureusement, le même problème persiste. Tout fonctionne très bien sur ma machine locale, et tous les Tests Unitaires passent, mais dès que je la pousse d'Azur et d'attendre plus de quelques minutes entre les demandes, je reçois cette erreur, lorsque vous essayez de récupérer une connexion à partir de la piscine:
springHikariCP - Connexion n'est pas disponible, la demande dépassé après 38268ms. SQLState: 08S01. ErrorCode: 0.
Mon HikariCP configuration est comme suit:
//Set up connection pool
HikariConfig config = new HikariConfig();
config.setDriverClassName("com.mysql.jdbc.Driver");
config.setJdbcUrl("jdbc:mysql://dblocation");
//Connection pool properties
Properties prop = new Properties();
prop.setProperty("user", "Username");
prop.setProperty("password", "Password");
prop.setProperty("verifyServerCertificate", "false");
prop.setProperty("useSSL","true");
prop.setProperty("requireSSL","true");
config.setDataSourceProperties(properties);
config.setMaximumPoolSize(20);
config.setConnectionTestQuery("SELECT 1");
config.setPoolName("springHikariCP");
config.setLeakDetectionThreshold(5000);
config.addDataSourceProperty("dataSource.cachePrepStmts", "true");
config.addDataSourceProperty("dataSource.prepStmtCacheSize", "250");
config.addDataSourceProperty("dataSource.prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("dataSource.useServerPrepStmts", "true");
dataSource = new HikariDataSource(config);
Toute aide serait grandement appréciée.
Je n'ai pas de bonne raison pour laquelle je ne suis pas en utilisant des pools de threads (encore obtenir mes pieds sous moi avec JDBC), mais de ce que j'ai lire, autoreconnect avec MySQL n'est pas fiable. Le
connection.isValid(int)
méthode est fiable à partir de ce que je sais. Votre commentaire implique que l'utilisation d'un pool de connexion pourrait potentiellement éliminer les détails de bas niveau comme celui - ci- est-ce le cas?Oui. Aussi, selon le pool de connexion, vous pouvez utiliser une requête de il utilise est valide (je recommande HikariCP que d'une piscine). Ce qui devrait supprimer automatiquement de connexion non valide à partir de la piscine de la création de nouvelles en cas de besoin. Par conséquent, vous n'avez pas vraiment besoin de reconnexion automatique juste une bonne piscine
Vous ne devriez pas être à l'aide du pilote/jdbcurl combo, mais la source de données de la classe à la place (comme il est expliqué sur le wiki de HikariCP) c'est vraiment que de la manière recommandée. (Je vais modifier ma réponse avec vos paramètres. Une chose à noter est que
HikariDataSource
s'étend HikariConfig
vous permet d'économiser un peu de code.Aussi pour la requête de test utiliser
/* ping */ select 1
de juste /* ping */
comme qui va déclencher une commande ping au lieu de l'exécution de la requête. Peut varier un peu de comportement.OriginalL'auteur JackB | 2016-02-02
Vous devez vous connecter pour publier un commentaire.
Je vous suggérons d'utiliser un bon Pool de connexions JDBC comme HikariCP qui, ensemble, avec une requête de validation qui va exécuter correctement les intervalles de vous donner fraîches et les connexions appropriées à chaque fois.
En supposant que vous utilisez le Printemps et xml pour configurer la source de données.
Par défaut valide les connexions à la caisse. Je suggère de l'essayer.
Que vous utilisez java bases de config je suggère ce qui suit
En fait, vous ne devriez pas utiliser un
connectionTestQuery
que désactiver le JDBC4isValid
vérifier. Vous pouvez encore voir l'erreur, mais votre application doivent encore travailler à mon humble avis.Ok, donc j'ai pensé à elle, et la réponse c'est super proche de cela, mais il est une clé de l'option de configuration manquant qui a fait le tour. Est-il casher pour modifier votre réponse à inclure, puis de l'accepter? Ou devrais-je ajouter mes propres répondre tous ensemble?
Eh bien, Si vous dites quelle est la clé d'une option de configuration je vais l'ajouter à la réponse.
Touche options de configuration qui fait le travail sont les suivants:
ds.setMaximumPoolSize(5);
ds.setMaxLifetime(30000);
ds.setMinimumIdle(5);
ds.setIdleTimeout(30000);
en fait Cela garantit qu'il n'existe toujours 5 connexions dans le pool qui ne sont jamais inactif pendant plus de 30 secondes.OriginalL'auteur M. Deinum
Il semble être causé par la variable système
wait_timeout
de MySQL.Pour MySQL 5.0, 5.1, 5.5, 5.6, la valeur par défaut pour
wait_timeout
est 28800 secondes (8 heures), et la valeur maximale pourwait_timeout
:Donc je pense que vous pouvez essayer d'utiliser une connexion jdbc à garder une requête ping à intervalle de quelques secondes, soit directement à l'aide d'une sorte de Pool de connexions JDBC cadre pour gérer les connexions jdbc automatiquement.
Espère que ça aide. En Ce Qui Concerne Meilleur.
OriginalL'auteur Peter Pan
en supposant que le code que vous avez maintenant pour '//la mise en place du pool de connexions' est appelé qu'une seule fois, comme les haricots création, pour initialiser la base de données.
avec cela, votre getConnection() serait tout:
et assurez-vous que wait_timeout dans mysql est réglé à la minute plus que maxLifetime dans hikaricp qui est par défaut 30 minutes
Espère que cette aide.
OriginalL'auteur Nitin