Frage

Ich brauche eine Auswahl auszuführen und dann einige der Zeilen in den ResultSet in einer atomaren Weise zu aktualisieren.

Der Code Ich bin mit Aussehen wie (vereinfacht):

stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery("SELECT ...");

while (rs.next()) {
    if (conditions_to_update) {
        rs.updateString(...);
        rs.updateRow();
    }
}
  • Kann ich garantieren, dass der Updates atomar ausgeführt werden werden? Wenn nicht, wie kann ich versichern?
  • Was passiert, wenn ein anderer Prozess die Datenbankzeile geändert hat, die Sie über updateRow() aktualisieren? Gibt es eine Möglichkeit die Zeilen in der ResultSet zu sperren?
War es hilfreich?

Lösung

Es ist wahrscheinlich ein ganzer Haufen von Technologien und Konzepten, die hier ins Spiel kommen, und die Dinge beginnen, ziemlich klebrig zu erhalten, wenn Sie Multi-Thread / Multi Anfrage Anwendungen unter Berücksichtigung starten.

Wie Iassevk erwähnt, sollten Sie in schauen Transaktionen rel="nofollow <

: - / a> die atomare Natur Ihres Updates, um sicherzustellen, ein sehr niedrige Ebene Beispiel etwas entlang der Linien von tun wäre,
...
con.setAutoCommit(false);
try {
  while (rs.next()) {
    if (conditions_to_update) {
      rs.updateString(...);
      rs.updateRow();
    }
  }
  con.setAutoCommit(true);
} catch (Exception ex) {
  //log the exception and rollback
  con.rollback();
} finally {
  con.close();
}

Alle Updates würden dann in derselben Transaktion chargiert werden. Wenn eines des Updates eine Ausnahme (wie ein ungültiger Wert oder die Verbindung andernfalls teilweise durch die Ergebnisse) erzeugt, würde die ganze Menge mehr rückgängig gemacht werden. (Schließlich hinzugefügt, weil ich ein Champion davon bin; p)

Dies ist jedoch nicht Ihr zweites Problem beheben, die zwei sind konkurrierende Methoden versuchen, die gleiche Tabelle zu aktualisieren - eine Race-Bedingung. Es gibt in meinem Kopf, zwei Ansätze hier - jeder hat seine Vor- und Nachteile

.

Der einfachste Ansatz wäre href="http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html" zum sperren - dies würde minimale Änderungen am Code erfordert aber einen ziemlich großen Nachteil hat. In der Annahme, dass, wie bei den meisten Anwendungen, es ist mehr lesen, dass der Schreib: die Tabellensperren verhindert, dass alle anderen Benutzer aus den Daten sehen, mit der Wahrscheinlichkeit wird der Code hängt, wartet, bis die Verriegelung zu lösen, bevor die Verbindung Time-out Tritte in und löst eine Ausnahme.

Je komplexer Ansatz besteht darin, sicherzustellen, dass die Verfahren zur Durchführung dieses Updates in einem Thread-sichere Art und Weise umgesetzt werden. Zu diesem Zweck:

  • Alle Updates für diese Tabelle über eine einzige Klasse
  • geben
  • implementiert, die Klasse ein Muster Singleton, oder macht die Aktualisierungsmethoden als statische Methoden
  • Die Update-Methoden verwenden, um das Synchronisierte Stichwort zu verhindern Rennbedingungen

Andere Tipps

Verwenden Transaktionen.

  

Was passiert, wenn ein anderer Prozess die Datenbankzeile geändert hat, die Sie über updateRow aktualisieren ()? Gibt es eine Möglichkeit die Zeilen im ResultSet zu sperren?

In Oracle können Sie irgendwie markieren bestimmte Zeilen für die Aktualisierung durch die folgende SQL-Ausgabe.

select cola, colB from tabA for update;

Die nächste Transaktion / Thread / app, die diese Zeile zu aktualisieren versucht, wird eine Ausnahme erhalten. sehen dies für weitere Details - http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:4530093713805

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