[Oracle] ORA-01555: snapshot too old: rollback

Hallo Leute,

ich hab mal wieder ein Oracle Problem. Und zwar tritt regelmässig folgender Fehler mit jeweils unterschiedlichen RB-Segmenten auf:

ORA-01555: snapshot too old: rollback segment number 9 with name „RBS7“ too small

Das Szenario schaut so aus:

Die Datenbank enthält nur eine Tabelle. Auf diese Tabelle werden von drei verschiedenen Prozessen ständig INSERT- und UPDATE-Befehle ausgeführt. Die Tabelle stellt eine Baumstruktur dar, d. h. hat einen FK auf sich selber.

Ein vierter Prozess löscht regelmässig (alle halben Stunden) Daten aus dieser Tabelle die zuvor von einem der anderen Prozesse mit einem Lösch-Flag gekennzeichnet wurden. Ausserdem verschiebt dieser Prozess Datensätze die noch kein Lösch-Flag haben aber älter als fünf Tage sind automatisch in eine andere Tabelle (zuerst UPDATE indem ein Flag gesetzt wird, dann INSERT in die andere Tabelle, dann DELETE).

Dieser vierte Prozess verwendet allerdings ein eigens für diesen Prozess angelegtes, größeres RB-Segment (über SET TRANSACTION USE ROLLBACK SEGMENT …).

Und in genau diesem viertem Prozess, der eigentlich ein anderes Rollback-Segment verwenden sollte, tritt obiger Fehler auf.

Hat da jemand eine Idee woran das liegen könnte?

Danke und Grüße,
Robert

hi!

eine möglichkeit ist, mehrere commits abzusetzen … wie groß ist eigentlich das „größere“ rollbacksegment?

passiert ein/das commit erst nach dem gesamten löschen?

unter 7.3 gab’s noch den bug (hab’s noch nicht probiert, ob das nun bei den neueren versionen schon herausen ist), daß du nach dem commit (daß den platz im rollback-segment nur freigibt) auch noch ein select absetzen müssen hast (um die daten im rollback-segment auch zu löschen)

grüße,
tomh

Hallo Tom,

eine möglichkeit ist, mehrere commits abzusetzen … wie groß
ist eigentlich das „größere“ rollbacksegment?

1 GB war das groß, wenn ich mich recht erinnere.

passiert ein/das commit erst nach dem gesamten löschen?

Ein commit nach dem Löschen. Ursprünglich hatten wir eine Prozedur die alle 1000 Datensätze ein commit macht, da hat unser Oracle-DBA aber gemeint, dass ein grosses RB-Segment die Sache auch regeln sollte. Zumindest dem Fehler nach ist es ja auch nicht das große RB-Segment das überläuft.

Aber danke für die Idee, eventuell sollten wir es mal mit der alten Version der Prozedur probieren.

Unsere aktuelle Vermutung ist gerade die, dass der Fehler auftritt, weil der Löschprozess sehr lange braucht (> halbe Stunde). Wir hatten auch Deadlock-Fehler die daher kommen könnten, dass nach einer halben Stunden dann für eine bestimmte Zeit lang der Löschprozess doppelt läuft.

Was wir jetzt herausgefunden haben ist, dass das Löschstatement unglücklich formuliert war, und zwar mit einer Abfrage ob ein Feld NULL ist, was den Index unwirksam macht und einen Full-Table-Scan auslöst. Der wiederum braucht extrem lange, da im Moment immer nur so ca. 50.000 Datensätze in der Tabelle stehen, aber früher mal über 1.000.000 drinnen waren und der Full-Table-Scan den gesamten Bereich der damals belegt war durchsucht (so hats auf jeden Fall ein inzwischen zur Hilfe geeilter Oracle-Auskenner erklärt).

Inzwischen habe ich auch ein interessantes Dokument zu dem Fehler gefunden: http://www.evdbt.com/CatsDogsORA01555.doc

Danke und Grüße, Robert

Hi Robert,

Nur eine kurze Frage: Verwendet ihr „select across commits“? Also etwas in der Form (Pseudocode):

for (get record from my\_1st\_table\_cursor)
 {
 delete from my\_other\_table...
**commit;**
 }

Das führt nämlich unter Umständen zum selben Fehler (wenn nämlich der Cursor aus dem Rollback Segment liest, das aber (wegen des commits) schon wieder als frei markiert worden ist).

Gruß,
TheBeast

Hallo,

Nur eine kurze Frage: Verwendet ihr „select across commits“?
Also etwas in der Form (Pseudocode):

Nein, sowas verwenden wir nicht, aber trotzdem danke für den Hinweis.

Grüße, Robert