Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Unterschied zwischen LockModeType Jpa

Ich würde zunächst zwischen optimistischen und pessimistischen Sperren unterscheiden, da sie sich in ihrem zugrunde liegenden Mechanismus unterscheiden.

Optimistisches Sperren wird vollständig von JPA gesteuert und erfordert nur eine zusätzliche Versionsspalte in DB-Tabellen. Es ist völlig unabhängig von der zugrunde liegenden DB-Engine, die zum Speichern relationaler Daten verwendet wird.

Auf der anderen Seite verwendet das pessimistische Sperren einen Sperrmechanismus, der von der zugrunde liegenden Datenbank bereitgestellt wird, um vorhandene Datensätze in Tabellen zu sperren. JPA muss wissen, wie diese Sperren ausgelöst werden, und einige Datenbanken unterstützen sie nicht oder nur teilweise.

Nun zur Liste der Sperrtypen:

  1. LockModeType.Optimistic
    • Wenn Entitäten ein Versionsfeld angeben, ist dies die Voreinstellung. Bei Entitäten ohne Versionsspalte funktioniert die Verwendung dieser Art von Sperre nicht garantiert bei jeder JPA-Implementierung. Dieser Modus wird normalerweise ignoriert, wie von ObjectDB angegeben. Meiner Meinung nach existiert es nur, damit Sie den Sperrmodus dynamisch berechnen und weitergeben können, selbst wenn die Sperre am Ende OPTIMISTISCH wäre. Nicht sehr wahrscheinlicher Anwendungsfall, aber es ist immer ein gutes API-Design, eine Option bereitzustellen, um sogar auf den Standardwert zu verweisen.
  • Beispiel:

       `LockModeType lockMode = resolveLockMode();
     A a = em.find(A.class, 1, lockMode);`
    
  1. LockModeType.OPTIMISTIC_FORCE_INCREMENT
  • Dies ist eine selten verwendete Option. Aber es könnte sinnvoll sein, wenn Sie die Referenzierung dieser Entität durch eine andere Entität sperren möchten. Mit anderen Worten, Sie möchten die Arbeit mit einer Entität sperren, auch wenn sie nicht geändert wurde, aber andere Entitäten können in Bezug auf diese Entität geändert werden.
  • Beispiel:Wir haben die Entität Book and Shelf. Es ist möglich, ein Buch zum Regal hinzuzufügen, aber das Buch hat keinen Verweis auf sein Regal. Es ist sinnvoll, das Verschieben eines Buches in ein Regal zu sperren, damit ein Buch nicht vor Ende dieser Transaktion (aufgrund einer anderen Transaktion) in einem anderen Regal landet. Um diese Aktion zu sperren, reicht es nicht aus, die aktuelle Bücherregalentität zu sperren, da das Buch noch nicht in einem Regal stehen muss. Es macht auch keinen Sinn, alle Ziel-Bücherregale zu sperren, da sie wahrscheinlich in verschiedenen Transaktionen unterschiedlich sein würden. Das einzige, was Sinn macht, ist, die Buchentität selbst zu sperren, auch wenn sie in unserem Fall nicht geändert wird (sie enthält keinen Verweis auf ihr Bücherregal).
  1. LockModeType.PESSIMISTIC_READ
  • dieser Modus ähnelt LockModeType.PESSIMISTIC_WRITE , aber in einer Sache anders:Bis eine Schreibsperre für dieselbe Entität durch eine Transaktion eingerichtet ist, sollte das Lesen der Entität nicht blockiert werden. Außerdem können andere Transaktionen mit LockModeType.PESSIMISTIC_READ gesperrt werden . Die Unterschiede zwischen WRITE- und READ-Sperren werden hier (ObjectDB) und hier (OpenJPA) gut erklärt. Wenn eine Entität bereits durch eine andere Transaktion gesperrt ist, löst jeder Versuch, sie zu sperren, eine Ausnahme aus. Dieses Verhalten kann so geändert werden, dass einige Zeit gewartet wird, bis die Sperre freigegeben wird, bevor eine Ausnahme ausgelöst und die Transaktion rückgängig gemacht wird. Geben Sie dazu javax.persistence.lock.timeout an Hinweis mit der Anzahl der zu wartenden Millisekunden, bevor die Ausnahme ausgelöst wird. Es gibt mehrere Möglichkeiten, dies auf mehreren Ebenen zu tun, wie im Java EE-Tutorial beschrieben.
  1. LockModeType.PESSIMISTIC_WRITE
  • Dies ist eine stärkere Version von LockModeType.PESSIMISTIC_READ . Beim WRITE Wenn eine Sperre vorhanden ist, verhindert JPA mit Hilfe der Datenbank, dass andere Transaktionen die Entität lesen und nicht nur schreiben, wie mit READ sperren.
  • Die Art und Weise, wie dies in einem JPA-Anbieter in Zusammenarbeit mit der zugrunde liegenden DB implementiert wird, ist nicht vorgeschrieben. In Ihrem Fall mit Oracle würde ich sagen, dass Oracle nichts in der Nähe eines READ bietet sperren. SELECT...FOR UPDATE ist eigentlich eher ein WRITE sperren. Es kann ein Fehler im Ruhezustand sein oder nur eine Entscheidung, statt benutzerdefinierten "weicheren" READ zu implementieren lock, das "härtere" WRITE Sperre wird stattdessen verwendet. Dies bricht meistens nicht die Konsistenz, hält aber nicht alle Regeln mit READ Schlösser. Sie könnten einige einfache Tests mit READ ausführen Sperren und Transaktionen mit langer Laufzeit, um herauszufinden, ob weitere Transaktionen READ erwerben können sperrt dieselbe Entität. Dies sollte möglich sein, nicht jedoch mit WRITE Schlösser.
  1. LockModeType.PESSIMISTIC_FORCE_INCREMENT
  • Dies ist ein weiterer selten verwendeter Sperrmodus. Es ist jedoch eine Option, bei der Sie PESSIMISTIC kombinieren müssen und OPTIMISTIC Mechanismen. Verwenden von einfachem PESSIMISTIC_WRITE würde in folgendem Szenario fehlschlagen:
    1. Transaktion A verwendet optimistisches Sperren und liest Entität E
    2. Transaktion B erwirbt WRITE-Sperre auf Entität E
    3. Transaktion B schreibt fest und gibt Sperre von E frei
    4. Transaktion A aktualisiert E und schreibt fest
  • in Schritt 4, wenn die Versionsspalte nicht durch Transaktion B inkrementiert wird, hindert nichts A daran, Änderungen von B zu überschreiben. Sperrmodus LockModeType.PESSIMISTIC_FORCE_INCREMENT zwingt Transaktion B, die Versionsnummer zu aktualisieren, und bewirkt, dass Transaktion A mit OptimisticLockException fehlschlägt , obwohl B pessimistische Sperren verwendet hat.
  1. LockModeType.NONE
  • Dies ist die Standardeinstellung, wenn Entitäten kein Versionsfeld bereitstellen. Dies bedeutet, dass keine Sperre aktiviert ist. Konflikte werden nach besten Kräften gelöst und nicht erkannt. Dies ist der einzige Sperrmodus, der außerhalb einer Transaktion erlaubt ist