Frage

Ich schreibe eine Anwendung, um eine MySQL -Datenbank zu analysieren, und ich muss köchelnd mehrere DMLs ausführen. zum Beispiel:

// 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
}

Ich deklariere eine Reihe von Datenobjekten, die jeweils eine eigene Verbindung zur Datenbank haben, was wiederum verschiedene Methoden für die Datenanalyse aufruft. Das Problem ist, dass alle Threads dieselbe Verbindung verwenden, daher werfen alle Aufgaben Aussehen aus: "Wartezeitüberschreitungen überschritten; versuchen Sie es zu starten, Transaktion neu zu starten."

Ich glaube, es gibt eine Möglichkeit, den Code so zu schreiben, dass ein bestimmtes Objekt eine eigene Verbindung hat und die erforderlichen Aufgaben unabhängig von jedem anderen Objekt ausführt. Zum Beispiel:

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).

Kannst du mich in die richtige Richtung verweisen?

Vielen Dank

War es hilfreich?

Lösung 2

Nach einiger Zeit des Gehirnbruchs habe ich meine eigenen Fehler herausgefunden ... Ich möchte dieses neue Wissen platzieren, also ... hier gehe ich

Ich habe eine sehr gemacht großer Fehler Durch die Deklaration des Verbindungsobjekts als statisches Objekt in meinem Code ... obwohl ich für jedes neue Datenobjekt, das ich erstellt habe, obwohl ich eine neue Verbindung erstellt habe, hat jede Transaktion eine einzige statische Verbindung durchgeführt.

Mit dieser ersten Ausgabe kehrte ich zurück zum Designtisch und stellte fest, dass mein Prozess war:

  1. Lesen Sie eine ID aus einer Eingangstabelle aus
  2. Nehmen Sie einen Datenblock in Bezug auf die in Schritt 1 gelesene ID, die in anderen Eingabetabellen gespeichert ist
  3. Crunchnummern: Lesen Sie die zugehörigen Eingabetabellen und verarbeiten Sie die darin gespeicherten Daten
  4. Speichern Sie die Ergebnisse in einer oder mehreren Ausgabetabellen
  5. Wiederholen Sie den Vorgang, während ich anhängige IDs in der Eingangstabelle habe

Nur durch die Verwendung einer dedizierten Verbindung zum Eingabemitteln und einer dedizierten Verbindung zum Schreiben von Ausgaben stieg die Leistung meines Programms ... aber ich brauchte viel mehr!

Mein ursprünglicher Ansatz für die Schritte 3 und 4 bestand darin, in jedem der Ergebnisse in die Ausgabe zu speichern, sobald ich sie hatte ... aber ich fand einen besseren Ansatz:

  • Lesen Sie die Eingabedaten
  • Crunch die Zahlen und setzen Sie die Ergebnisse in eine Reihe von Warteschlangen (eine für jede Ausgangstabelle).
  • Ein getrennter Thread überprüft jede Sekunde, wenn in einer der Warteschlangen Daten vorhanden sind. Wenn in den Warteschlangen Daten vorhanden sind, schreiben Sie sie in die Tabellen.

Durch die Dividierung von Eingangs- und Ausgangsaufgaben unter Verwendung verschiedener Verbindungen und durch Umleitung des Kernvorgangsausgangs in eine Warteschlange und durch Verwendung eines dedizierten Threads für Ausgabespeicheraufgaben habe ich endlich das erreicht, was ich wollte: Multithreadd DML -Ausführung!


Ich weiß, dass es bessere Ansätze für dieses spezielle Problem gibt, aber dieser funktioniert ziemlich gut.

Also ... wenn jemand mit einem solchen Problem hängt ... Ich hoffe, das hilft.

Andere Tipps

Ich denke, das Problem ist, dass Sie eine Menge mittlerer, transaktionaler und anhaltender Logik in einer Klasse verwechselt haben.

Wenn Sie sich direkt mit Ergebnissen zur Verfügung stellen, denken Sie nicht in sehr objektorientierter Weise über Dinge nach.

Sie sind schlau, wenn Sie herausfinden können, wie die Datenbank einige Ihrer Berechnungen durchführt.

Wenn nicht, würde ich empfehlen, Verbindungen für die minimale Zeit offen zu halten. Öffnen Sie eine Verbindung, erhalten Sie das Ergebnis, ordnen Sie sie in eine Objekt- oder Datenstruktur ab, schließen Sie das Ergebnis und die Verbindung im lokalen Bereich und geben Sie die zugeordnete Objekt-/Datenstruktur für die Verarbeitung zurück.

Sie halten die Persistenz und verarbeiten die Logik auf diese Weise. Sie sparen sich viel Trauer, indem Sie Verbindungen kurzlebig halten.

Wenn eine gespeicherte Verfahrenslösung langsam ist, kann dies auf eine schlechte Indizierung zurückzuführen sein. Eine andere Lösung wird ebenso schlecht, wenn nicht sogar schlechter. Versuchen Sie, den Plan zu erklären und zu prüfen, ob eine Ihrer Abfragen den Tabellencan verwendet. Wenn ja, haben Sie einige Indizes hinzuzufügen. Es könnte auch auf große Rollback-Protokolle zurückzuführen sein, wenn Ihre Transaktionen langlebig sind. Es gibt viel, was Sie tun könnten und sollten, um sicherzustellen, dass Sie mit der Lösung, die Sie vor dem Wechseln haben, alles möglich gemacht haben. Sie könnten viel Anstrengungen unternehmen und sich trotzdem nicht mit der Grundursache befassen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top