Oracle MERGE verursacht eine DuplicateKeyException bei hoher Parallelität mit zusammengesetztem PrimärschlüsselJava

Java-Forum
Anonymous
 Oracle MERGE verursacht eine DuplicateKeyException bei hoher Parallelität mit zusammengesetztem Primärschlüssel

Post by Anonymous »

Ich stoße auf eine Race-Bedingung, wenn ich eine Oracle MERGE-Anweisung aus einer Spring Boot-Anwendung verwende, und ich versuche zu verstehen, warum das passiert und wie man damit richtig umgeht.
Wenn mehrere gleichzeitige Anfragen mit demselben zusammengesetzten Primärschlüssel die API erreichen, schlägt die MERGE-Anweisung gelegentlich mit folgendem Fehler fehl:

Code: Select all

ORA-00001: unique constraint violated
Fehlerdetails:

Code: Select all

org.springframework.dao.DuplicateKeyException:

PreparedStatementCallback; SQL [MERGE INTO USER_ACTIONS USING (
SELECT ? AS SESSION_ID, ? AS ITEM_ID, ? AS USER_ID, ? AS ACTION_ID,
? AS PAYLOAD, ? AS CREATED_AT, ? AS UPDATED_AT FROM dual
) s
ON (t.SESSION_ID = s.SESSION_ID
AND t.ITEM_ID = s.ITEM_ID
AND t.USER_ID = s.USER_ID
AND t.ACTION_ID = s.ACTION_ID)
WHEN MATCHED THEN UPDATE SET
t.PAYLOAD = s.PAYLOAD,
t.UPDATED_AT = s.UPDATED_AT
WHEN NOT MATCHED THEN INSERT (
SESSION_ID, ITEM_ID, USER_ID, ACTION_ID, PAYLOAD, CREATED_AT, UPDATED_AT
) VALUES (
s.SESSION_ID, s.ITEM_ID, s.USER_ID, s.ACTION_ID, s.PAYLOAD, s.CREATED_AT, s.UPDATED_AT
)]; ORA-00001: unique constraint (DUMMY_SCHEMA.USER_ACTIONS_PK) violated

nested exception is java.sql.SQLIntegrityConstraintViolationException:
ORA-00001: unique constraint (DUMMY_SCHEMA.USER_ACTIONS_PK) violated

at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(
SQLExceptionSubclassTranslator.java:89
)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(
AbstractFallbackSQLExceptionTranslator.java:70
)
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1541)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:667)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:960)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:1015)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(
NamedParameterJdbcTemplate.java:321
)
at com.example.demo.dao.UserActionDaoImpl.mergeAction(UserActionDaoImpl.java:45)
(rest of stack trace)

Caused by: java.sql.SQLIntegrityConstraintViolationException:
ORA-00001: unique constraint (DUMMY_SCHEMA.USER_ACTIONS_PK) violated
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:494)
(rest of stack trace)

Dies geschieht, obwohl die Tabelle einen zusammengesetzten Primärschlüssel hat und MERGE nach vorhandenen Zeilen sucht.
Umgebung
  • Spring Boot REST API
  • Oracle-Datenbank
  • 4 Anwendungsinstanzen
  • Lasttest: ~1100 gleichzeitige Benutzer, 1 Minute Hochlauf
Tabelle
Zusammengesetzter Primärschlüssel:

Code: Select all

(USER_ID, ITEM_ID, VERSION_ID, ACTION_ID)
MERGE (vereinfacht)

Code: Select all

MERGE INTO user_actions t
USING (
SELECT
:sessionId AS session_id,
:itemId    AS item_id,
:userId    AS user_id,
:versionId AS version_id,
:actionId  AS action_id
FROM dual
) s
ON (
t.session_id = s.session_id
AND t.item_id = s.item_id
AND t.user_id = s.user_id
AND t.action_id = s.action_id
)
WHEN MATCHED THEN UPDATE
SET t.updated_at = :updatedAt
WHEN NOT MATCHED THEN INSERT (...);
Warum kann Oracle MERGE immer noch ORA-00001 bei gleichzeitigen Anfragen mit demselben Schlüssel erzeugen und wie sollte dies in einer Spring Boot-Anwendung korrekt gehandhabt werden?
Alle Erkenntnisse von Leuten, die sich mit dieser Art von Upsert-Szenario mit hoher Parallelität befasst haben, wären wirklich hilfreich.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post