Ich habe eine Tabelle, die ein paar Spalten und eine Sequenz, die für den Wert dieser Spalten erhöht hat. Für (ein vereinfachtes) Beispiel:Ruhezustand Gleichzeitigkeit Problem mit Auswahl max() und dann einfügen() + 1
A | B | SEQ
===========
x | x | 1
x | x | 2
x | x | 3
x | y | 1
x | x | 4
z | x | 1
x | y | 2
Ich habe mehrere Prozesse, die eine Feder-Anwendung mit der Ruhe verwenden werden und wird sowohl A als auch B, wählen Sie den Maximalwert für A und B annehmen, und dann max + 1
einzufügen.
So zum Beispiel oben, wenn jemand A vorgesehen = z und B = x, würden wir wählen, erhalten 1 und legen Sie z, x, 2.
Wenn jemand A = z und die B = z (keine vorhandenen Zeilen übereinstimmen), der Prozess würde abfragen und keine Max (oder ein Maximum von Null) finden und dann z, z, 1. einfügen.
Angenommen, dass eine einfache Sequenz hier nicht funktioniert, weil die Spaltengröße für Sequenz wird nicht groß genug sein, um eine Sequenz über alle Werte von A und B zu ermöglichen, und weil das tatsächliche Problem komplexer ist als das oben angegebene Beispiel.
Ich kann mir vier Lösungen für dieses Problem vorstellen, kann funktionieren aber ich frage mich, ob es eine Standardmethode ist, dies zu tun, und ich bin mir nicht sicher, wie diese Methoden mit Hibernate und ohne implementiert werden können Verwenden benutzerdefinierter Oracle-Funktionen:
- Führen Sie die
select max()
, versuchen Sie, einzufügen. Wenn ein Problem mit dem gemeinsamen Zugriff auftritt, wird einer der Threads fehlschlagen und der Code wird so oft wie erforderlich wiederholt, bis die Einfügung funktioniert. Mit Hibernate könnte dies bedeuten, dass wir mitten in unserer Transaktion manuell leeren müssten. - Führen Sie einen
select for update
oder einen anderen Mechanismus durch, um die Zeilen zu sperren, die uns wichtig sind (diejenigen, die A und B entsprechen), wenn wir die ersteselect max()
machen. Dies wird andere Prozesse blockieren, die ebenfalls versuchen, das Maximum zu finden, und dann können wir unsere Zeile einfügen, und wenn das Txn festgeschrieben wird, können die ausgewählten Elemente ausgewählt werden. Ich bin mir nicht sicher, wie das funktionieren würde, wenn es derzeit keine Zeilen in der Tabelle gibt, die mit A und B übereinstimmen. - Erstellen Sie eine gespeicherte Prozedur, die das Maximum automatisch auswählen und einfügen kann. Ich möchte jedoch gespeicherte Prozesse möglichst vermeiden.
- In Hibernate gibt es eine Möglichkeit, eine Einfügung (
select max() + 1
) durchzuführen und den Wert aus einer Spalte, die in einer Anweisung eingefügt wurde, zurückzugeben?
Danke für den Vorschlag. Wir werden wahrscheinlich keine Löschungen in dieser Tabelle haben. 'partition by' würde natives SQL erfordern und das möchte ich vermeiden. –
Sie sind so wählerisch, zuerst nicht storeproc, jetzt nicht native sql verwenden. Oracle hat 'row_number() über (Partition' –
hast du dieses überprüft? Http://stackoverflow.com/questions/3616321/concurrent-updates-handling-in-hibernate?rq=1 –