webentwicklung-frage-antwort-db.com.de

Warum brauche ich Transaction in Hibernate für schreibgeschützte Vorgänge?

Warum brauche ich Transaction in Hibernate für schreibgeschützte Vorgänge?

Setzt die folgende Transaktion eine Sperre in die DB?

Beispielcode zum Abrufen aus der DB:

Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); // why begin transaction?
//readonly operation here

tx.commit() // why tx.commit? I don't want to write anything

Kann ich session.close() anstelle von tx.commit() verwenden?

91
user93796

Möglicherweise haben Sie tatsächlich Gründe, Transaktionen als schreibgeschützt zu kennzeichnen.

  1. Transaktionen zum Lesen sehen in der Tat merkwürdig aus, und in diesem Fall markieren die Benutzer häufig keine Methoden für Transaktionen. JDBC erstellt jedoch trotzdem eine Transaktion. Es funktioniert nur in autocommit=true, Wenn nicht explizit eine andere Option festgelegt wurde.
  2. Es gibt jedoch keine Garantie dafür, dass Ihre Methode nicht in die Datenbank schreibt. Wenn Sie Methode als @Transactional(readonly=true) markieren, versetzt Spring die JDBC-Transaktion in einen Nur-Lese-Modus. Sie bestimmen also, ob in diesem Rahmen tatsächlich in DB geschrieben werden kann Transaktion. Wenn Ihre Architektur umständlich ist und einige Teammitglieder die Änderungsabfrage möglicherweise dort ablegen, wo dies nicht erwartet wird, weist Sie dieses Flag auf den problematischen Ort hin.
  3. Auch Nur-Lese-Transaktionen können von DBs optimiert werden, dies ist jedoch natürlich DB-spezifisch. Z.B. MySQL hat dies nur in InnoDB ab Version 5.6.4 unterstützt.
  4. Wenn Sie nicht direkt JDBC verwenden, sondern einen ORM, ist dies möglicherweise problematisch. Die Hibernate-Community gibt beispielsweise an, dass das Arbeiten außerhalb von Transaktionen zu unvorhersehbarem Verhalten führen kann. Dies liegt daran, dass der Ruhezustand die Transaktion öffnet, sie jedoch nicht von selbst schließt. Daher wird die Verbindung an den Verbindungspool zurückgegeben, wobei die Transaktion nicht festgeschrieben wird. Was passiert dann? JDBC schweigt, daher ist dies implementierungsspezifisch (MySQL setzt die Transaktion zurück, Oracle verpflichtet sich dazu). Dies kann auch auf der Ebene des Verbindungspools konfiguriert werden (z. B. C3P0 gibt Ihnen eine solche Option, standardmäßig Rollback).
  5. Eine andere Sache, wenn es um Ruhezustand geht, setzt Spring den FlushMode für schreibgeschützte Transaktionen auf MANUAL, was zu anderen Optimierungen führt, wie zum Beispiel, dass keine Dirty Checks erforderlich sind.
  6. Möglicherweise möchten Sie die Transaktionsisolationsstufe überschreiben oder explizit festlegen. Dies wirkt sich auch auf Lesetransaktionen aus, da Sie nicht festgeschriebene Änderungen lesen oder nicht lesen möchten, Phantom-Lesevorgängen ausgesetzt sind usw.

Zusammenfassend kann man beides sagen, aber man muss die Konsequenzen verstehen.

118

Alle Datenbankanweisungen werden im Kontext einer physischen Transaktion ausgeführt, auch wenn wir keine expliziten Transaktionsgrenzen deklarieren (BEGIN/COMMIT/ROLLBACK).

Wenn Sie Transaktionsgrenzen nicht explizit deklarieren, muss jede Anweisung in einer separaten Transaktion ausgeführt werden (autocommit -Modus). Dies kann sogar zum Öffnen und Schließen einer Verbindung pro Anweisung führen, es sei denn, Ihre Umgebung kann die Bindung von Verbindungen pro Thread verarbeiten.

Wenn Sie einen Service als @Transactional Deklarieren, erhalten Sie eine Verbindung für die gesamte Transaktionsdauer, und alle Anweisungen verwenden diese einzelne Isolationsverbindung. Dies ist viel besser, als überhaupt keine expliziten Transaktionen zu verwenden.

Bei großen Anwendungen treten möglicherweise viele gleichzeitige Anforderungen auf, und Reduzierung der Anforderungsrate für die Datenbankverbindungserfassung verbessert auf jeden Fall die Gesamtleistung Ihrer Anwendung.

JPA erzwingt keine Transaktionen für Leseoperationen. Nur Schreibvorgänge lösen eine für eine Transaktion erforderliche Ausnahme aus, wenn Sie vergessen, einen Transaktionskontext zu starten. Trotzdem ist es immer besser, Transaktionsgrenzen auch für schreibgeschützte Transaktionen zu deklarieren (im Frühjahr können Sie mit @Transactional Schreibgeschützte Transaktionen markieren, was einen großen Leistungsvorteil bietet).

35
Vlad Mihalcea

Transaktionen setzen in der Tat Sperren für die Datenbank - gute Datenbank-Engines behandeln gleichzeitige Sperren auf vernünftige Weise - und sind bei schreibgeschützter Verwendung nützlich, um sicherzustellen, dass keine andere Transaktion Daten hinzufügt, die Ihre Ansicht inkonsistent machen. Sie möchten immer eine Transaktion (obwohl es manchmal sinnvoll ist, die Isolationsstufe zu optimieren, ist es am besten, dies zunächst nicht zu tun). Wenn Sie während Ihrer Transaktion nie in die Datenbank schreiben, ist das Festschreiben und Zurücksetzen der Transaktion gleich (und sehr günstig).

Wenn Sie Glück haben und Ihre Abfragen für die Datenbank so sind, dass der ORM sie immer einzelnen SQL-Abfragen zuordnet, können Sie ohne explizite Transaktionen davonkommen, abhängig vom integrierten Autocommit-Verhalten der Datenbank ORMs sind jedoch relativ komplexe Systeme, so dass es nicht ungefährlich ist, sich auf ein solches Verhalten zu verlassen, wenn Sie nicht viel mehr Arbeit darauf verwenden, zu überprüfen, was die Implementierung tatsächlich tut. Das Schreiben der expliziten Transaktionsgrenzen ist weitaus einfacher (insbesondere, wenn Sie dies mit AOP oder einer ähnlichen ORM-gesteuerten Technik tun können; ab Java 7) könnten Try-with-Resources verwendet werden auch ich nehme an).

16
Donal Fellows

Es spielt keine Rolle, ob Sie nur lesen oder nicht - die Datenbank muss weiterhin die Ergebnismenge verfolgen, da andere Datenbankclients möglicherweise Daten schreiben möchten, die Ihre Ergebnismenge ändern würden.

Ich habe fehlerhafte Programme gesehen, die riesige Datenbanksysteme töten, weil sie nur Daten lesen, aber niemals festschreiben, wodurch das Transaktionsprotokoll wächst, weil die Datenbank die Transaktionsdaten nicht vor einem COMMIT oder ROLLBACK freigeben kann, selbst wenn der Client nichts getan hat stundenlang.

13
Ingo