Aide avec des fils java ou exécuteurs: exécution de plusieurs selects MySQL, insertions et mises à jour simmultaneously

StackOverflow https://stackoverflow.com/questions/2953955

Question

Je vous écris une application pour analyser une base de données MySQL, et je dois exécuter plusieurs DML simmultaneously; par exemple:

// In ResultSet rsA: Select * from A;
rsA.beforeFirst();
while (rsA.next()) {
   id = rsA.getInt("id");
   // Retrieve data from table B: Select * from B where B.Id=" + id;
   // Crunch some numbers using the data from B
   // Close resultset B
}

Je déclare un tableau d'objets de données, chacun avec sa propre connexion à la base de données, ce qui appelle plusieurs méthodes pour l'analyse des données. Le problème est tous les threads utilisent la même connexion, donc toutes les tâches jettent exceptios: « délai de verrouillage d'attente dépassé, transaction redémarrage essayer »

Je crois qu'il ya une façon d'écrire le code dans une telle façon que tout objet donné a sa propre connexion et exécute les tâches requises indépendantes de tout autre objet. Par exemple:

DataObject dataObject[0] = new DataObject(id[0]);
DataObject dataObject[1] = new DataObject(id[1]);
DataObject dataObject[2] = new DataObject(id[2]);
...
DataObject dataObject[N] = new DataObject(id[N]);
// The 'DataObject' class has its own connection to the database, 
// so each instance of the object should use its own connection. 
// It also has a "run" method, which contains all the tasks required.
Executor ex = Executors.newFixedThreadPool(10);

for(i=0;i<=N;i++) {
   ex.execute(dataObject[i]);
}
// Here where the problem is: Each instance creates a new connection,
// but every DML from any of the objects is cluttered in just one connection
// (in MySQL command line, "SHOW PROCESSLIST;" throws every connection, and all but
// one are idle).

Pouvez-vous me diriger dans la bonne direction?

Merci

Était-ce utile?

La solution 2

Après un certain temps de rupture du cerveau, je me suis dit mes propres erreurs ... Je veux mettre ces nouvelles connaissances, donc ... je vais ici

J'ai fait un très grosse erreur en déclarant la connexion comme objet un objet statique dans mon code ... si évidemment, malgré que j'ai créé une nouvelle connexion pour chaque objet de nouvelles données que j'ai créé, chaque transaction est passé par une seule, statique, connexion.

Avec cette première question corrigé, je suis retourné à la table de conception, et se rendit compte que mon processus était:

  1. Lire un identifiant d'une table d'entrée
  2. Prendre un bloc de données relatives à l'Id lu à l'étape 1, stockée dans d'autres tables d'entrée
  3. Numéros Crunch: lire les tableaux d'entrée connexes et traiter les données stockées dans les
  4. Enregistrer les résultats dans une ou plusieurs tables de sortie
  5. Répétez le processus pendant que je suis en attente Ids dans la table d'entrée

Juste en utilisant une connexion dédiée à la lecture d'entrée et une connexion dédiée à l'écriture de sortie, la performance de mon programme a augmenté ... mais je avais besoin beaucoup plus!

Mon approche originale pour les étapes 3 et 4 était de sauver dans la sortie chacun des résultats dès que je les avais ... Mais je l'ai trouvé une meilleure approche:

  • Lire les données d'entrée
  • Crunch les chiffres, et mettre les résultats dans un groupe de files d'attente (une pour chaque table de sortie)
  • A séparé fil vérifie toutes les secondes s'il y a des données dans l'une des files d'attente. S'il y a des données dans les files d'attente, écrire aux tables.

Ainsi, en divisant entrée et de tâches de sortie à l'aide de connexions différentes, et en redirigeant la sortie de processus de base à une file d'attente, et en utilisant un thread dédié pour les tâches de stockage de sortie, j'ai finalement obtenu ce que je voulais: multithread DML exécution


Je sais qu'il ya de meilleures approches à ce problème particulier, mais celui-ci fonctionne très bien.

Alors ... si quelqu'un est coincé avec un problème comme celui-ci ... J'espère que cela aide.

Autres conseils

Je pense que le problème est que vous avez confondu beaucoup de niveau intermédiaire, logique transactionnelle et persistante dans une classe.

Si vous traitez directement avec ResultSet, vous n'êtes pas penser à des choses d'une façon très orientée objet.

Vous êtes intelligent si vous pouvez comprendre comment obtenir la base de données certains de vos calculs.

Sinon, je vous recommande garder les connexions ouvertes pour le temps minimum possible. Ouvrez une connexion, obtenir le ResultSet, la carte dans une structure d'objet ou de données, à proximité ResultSet et connexion portée locale, et renvoyer l'objet mis en correspondance / structure de données pour le traitement.

Vous gardez la persistance et la logique de traitement séparé de cette façon. Vous vous épargner beaucoup de chagrin en gardant les connexions de courte durée.

Si une solution de procédure stockée est-il pourrait être lente en raison de l'indexation médiocre. Une autre solution fonctionne aussi mal sinon pire. Essayez de lancer EXPLAIN PLAN et voir si l'un de vos requêtes utilisent TABLE SCAN. Si oui, vous avez des index à ajouter. Il pourrait aussi être dû à de grands journaux d'annulation si vos transactions sont en cours d'exécution à long. Il y a beaucoup que vous pouvez et devez faire pour vous assurer que vous avez fait tout son possible avec la solution que vous avez avant commutation. Vous pouvez aller à beaucoup d'efforts et encore traitent pas la cause racine.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top