ich einen Batch-Job mit zwei Schritten habenSpring Batch: Alternative zu JpaPagingItemReader, die bewirkt, dass ORA-01555
- Schritt 1: auf externe Datenbank gehen, gespeicherte Prozedur aufrufen, JPA-Entitäten zusammenstellen und sie in interne persistieren Datenbank mit dem Flag NOT_PROCESSED.
- Schritt 2: Schleife durch gerade gespeichert Einheiten mit Flagge NOT_PROCESSED, verarbeiten sie und aktualisiert Einheit zurückschreiben (nicht aktualisiert, die die Flagge)
Sobald alle von ihnen verarbeitet werden, die die Flagge für alle von ihnen wird auf VERARBEITET aktualisiert. I.e. aktualisiere alles oder nichts.
Der Schritt 1 ist in Ordnung und funktioniert ziemlich glatt.
Der Schritt 2 ist im Grunde JpaPagingItemReader mit pageSize = 4, Satz von Prozessoren (meist http Aufrufe) und JpaItemWriter mit Commit-Intervall = 1. (Ich weiß, dass es pageSize gleich Commit-Intervall ist, es ist genau das, was ich habe) Es ist auch ein Multithread-Schritt mit 10 Threads, die den Job erledigen.
Das heißt auf der Stufe 2 I zwei Art von Anfragen haben:
lesen:
select * from ENTITY where processed=false order by id
Blättern in zwei Abfragen verschachteltselect ... from (select .. where rownum < M) where rownum >= N
schreiben:
update ENTITY set .. where id = ID
Für Irgendein Grund, wenn ich genug Entitäten habe, werde ich berüchtigt:
Ora-01555, Snapshot zu alt: Rollback-Segment mit dem Namen „“ zu klein
Ich weiß nicht, genauer Grund dieses Fehlers (stat rückgängig machen nichts schlecht zeigen, hoffentlich DBAs Ich werde den Schuldigen bald finden), aber in der Zwischenzeit denke ich, dass das, was Leseabfrage tut, furchtbar schlecht ist. Solche Paging-Abfragen sind sowieso für eine Datenbank schwierig, aber ich denke, wenn Sie die Einträge lesen und gleichzeitig aktualisieren, die Sie lesen, kann dies zu solchen Fehlern führen.
Ich möchte den Ansatz in Schritt 2 ändern. Anstatt Seiten einzulesen. Ich möchte alle IDs in den Speicher nur einmal lesen (d. H. Gib mir IDs aller Entitäten, die ich verarbeiten muss) und gebe dann jedem Thread die ID aus dieser Liste. Der erste Prozessor in der Kette erhält die Entity durch die ID durch JPA. Auf diese Weise aktualisiere und schreibe ich die Entitäten nacheinander und gleichzeitig lese ich die IDs, die ich nur einmal brauche.
Mein Problem ist, dass ich keine Out-of-the-Box-Lösung für solche Leser finden konnte. Kann ich irgendetwas dafür verwenden?
Warum führen Sie sowohl select + update als eine einzelne SQL-Anweisung aus? Auch was ist dein Isolationslevel? – ibre5041
Da, um Werte für das Update zu erhalten, gibt es eine sehr komplizierte Logik, wenn ich zu stark vereinfache - das Update hängt von externen Serviceaufrufen ab. Standard für Orakel, afair wird gelesen. –
Sie können diesen Fehler aus zwei Hauptgründen erhalten, 1. wenn Sie lobs ändern, 2. dauert die Ausführung Ihrer Abfrage zu viel Zeit. Das "zu viel" wird normalerweise als Spalte TUNED_UNDORETENTION aus der Sicht v $ undostat definiert. Dadurch wird angezeigt, was für eine sinnvolle Aufbewahrungsfrist für Ihre Datenbank mit bestimmter UNDO tbs-Größe und bestimmter Transaktionsaktivität gilt. – ibre5041