[Oracle] ORA-01552 unter Last

Hallo Leute,

ich habe auf einem Oracle-Server ein kleines Problem. Es handelt sich um einen Server der von einem Uni-Institut für eine Übung zur Verfügung gestellt wird, d. h. es arbeiten relativ viele Studenten (> 50) mit sqlplus gleichzeitig auf dem Server. Es werden wahrscheinlich relativ oft DDLs und INSERTs ausgeführt, aber auch SELECTs.

Folgender Fehler tritt recht häufig bei DDLs und INSERTs auf, allerdings nicht reproduzierbar, hängt scheinbar irgendwie mit der Last o. ä. zusammen:

ORA-01552: cannot use system rollback segment for non-system tablespace ‚TBS_DBLUE‘

Die Erklärung von Oracle (unter http://technet.oracle.com/doc/server.815/a67785/e150…) ist - zumindest für mich - eher nichtssagend.

Ich bin mir nicht ganz sicher als welcher Benutzer man dort eingeloggt ist, bei sqlplus übergeht man die Frage nach dem Benutzer mit Eingabe.

Hat jemand Tips was das sein könnte?

Grüße, Robert

Hallo Robert,

Ich nehme an, Dein Problem hängt mit einer zu geringen Anzahl verfügbarer Rollback-Segmente (RBS) und idle Sessions (die DML durchgeführt und dann lange Zeit kein Commit/Rollback gemacht haben) zusammen.
Mich wundert nur, dass du vorher keine anderen Fehler (siehe 4.) erhältst. Hast du mal im Alertlog nachgesehen?

Mögliche Fehlerursache:

  1. es existieren nur wenige (bzw. nur ein) Rollback-Segment(e)
  2. eines der RBS wird gleichzeitig von mehreren Usern verwendet
  3. mind. einer der User macht (sehr)lange Zeit kein Commit/Rollback
  4. die offene Transaktion führt dazu, das das verwendete RBS
    ständig erweitert wird, bis es an die RBS-Tablespacegrenze
    stößt. ORA-1650 „unable to extend rollback segment %s by %s
    in tablespace %s“ oder ORA-1562 „failed to extend rollback
    segment number %s“
  5. das RBS wird als full markiert
  6. beim nächsten DML/DDL Versuch wird das SYSTEM-RBS verwendet,
    was zu ORA-01552 führt

Lösung: höhere Anzahl an RBS oder disziplinierte User, die ihre
Transaktionen zeitnah duch Commit/Rollback abschließen.

Ich hoffe das hilft Dir ein wenig weiter.

Gruß

Tom

Hallo Robert,

also erstens sind 50 User für Oracle nix (das ganze hat also auch nicht mit „Last“ zu tun).

Zweitens ist das Problem mit minimalen Grundlagen lösbar (4. Tag DBA-Kurs).

Drittens ist die Fehlermeldung richtig und verständlich.

Offengestanden finde ich es sehr seltsam, dass 50 Jungakademiker auf einem Oraclesystem arbeiten und niemand weiss wie es zu bedienen ist. (Sicherlich nicht dein Fehler !) Leider bleibt dann häufig der Eindruck, Oracle sei schlecht oder zumindestens schwer zu bedienen. Beides ist falsch - man muss nur einen minimalen Standard an Ausbildung erfüllen. Traurig nur, dass einige dieser Akademiker später Entscheidungen fällen werden …

Aber nun zu deinem Problem:

  1. Ich vermute, du hast mehr als einen Tablespace (Select * from v$tablespace). Einer davon heisst SYSTEM

  2. Ich vermute , du hast zwar online Rollback-Segmente (RBS) - aber nur im SYSTEM-Tablespace (select segment_name, tablespace_name, status from dba_rollback_segs).

  3. Ich vermute, der beschiebene Fehler tritt auf, wenn du in einem Nicht-System-Tablespace etwas veränderst (select table_name, tablespace_name from dba_tables).

Doku : „Cause: An attempt was made to use the system rollback segment for operations involving non-system tablespace. […]“

Lösung :
Lege ein nicht Rollback-Segment in einem der Nicht-System-Tablespaces an. Besser noch : Lege einen neuen Tablespace extra für die Rollback Segmente an.

Doku: „Action: Create one or more private/public segment(s), shut down and restart. May need to modify the initialization parameter ROLLBACK_SEGMENTS to acquire private rollback segment. […]“

Beispielskript kommt noch - ich muss erst an den anderen Rechner.

Bis gleich der Janus

skript
****************************************************************
* Start Skript *
****************************************************************

CREATE TABLESPACE rbs01
DATAFILE ‚rbs01.dbf‘ – deine Pfadangabe nicht vergessen
SIZE 50M
DEFAULT STORAGE (INITIAL 200k
NEXT 200k
MINEXTENTS 20
PCTINCREASE 0)
/

CREATE ROLLBACK SEGMENT rbsA1
TABLESPACE rbs01
STORAGE (OPTIMAL 4000k)
/

CREATE ROLLBACK SEGMENT rbsA2
TABLESPACE rbs01
STORAGE (OPTIMAL 4000k)
/

CREATE ROLLBACK SEGMENT rbsA3
TABLESPACE rbs01
STORAGE (OPTIMAL 4000k)
/

CREATE ROLLBACK SEGMENT rbsA4
TABLESPACE rbs01
STORAGE (OPTIMAL 4000k)
/

CREATE ROLLBACK SEGMENT rbsA5
TABLESPACE rbs01
STORAGE (OPTIMAL 4000k)
/

ALTER ROLLBACK SEGMENT rbsA1 ONLINE;
ALTER ROLLBACK SEGMENT rbsA2 ONLINE;
ALTER ROLLBACK SEGMENT rbsA3 ONLINE;
ALTER ROLLBACK SEGMENT rbsA4 ONLINE;
ALTER ROLLBACK SEGMENT rbsA5 ONLINE;

****************************************************************
* Ende Skript *
****************************************************************

Die RBS sind jetzt angelegt und online
(SELECT segment_name, tablespace_name, status
FROM dba_rollback_segs).

Um sie auch nach einem Neustart der Instanz verfügbar zu haben, musst du sie nun noch in deiner Parameterdatei (init.ora) eintragen.

ROLLBACK_SEGMENTS=(rbsA1,rbsA2,rbsA3,rbsA4,rbsA5)

Aber Vorsicht : Den bestehenden Eintrag nicht überschreiben - nur ergänzen.

Probleme, Fragen und eventuelle Fehlermeldungen kannst du mir auch direkt mailen.

Gruß der Janus

PS: Normalerweise empfiehlt man bei einer (produktiven) OLTP-DB 1 RBS pro 10 User oder max. 4 parallele Transaktionen pro RBS.
Daher solltest du vielleicht noch mehr RBS anlegen.

Nun noch 2 Skripte zum Thema:

****************************************************************
* Start Skript *
****************************************************************



– This script provides TRANSACTION INFORMATION in a ROLLBACK SEGMENT for a
– particular OBJECT (Query v$locked_object, v$transaction).

– DESCRIPTION:
– OS USER = OS User
– DB USER = DB User
– SCHEMA = Object Owner
– OBJECT Name = Name of Object
– TYPE = Type of Object
– RBS = Rollback Segment Being Used
– # of Records = # of Records for this object in this transaction.

SELECT substr(a.os_user_name,1,8) „OS User“ ,
substr(a.oracle_username,1,8) „DB User“ ,
substr(b.owner,1,8) „Schema“ ,
substr(b.object_name,1,20) „Object Name“ ,
substr(b.object_type,1,10) „Type“ ,
substr(c.segment_name,1,5) „RBS“
FROM v$locked_object a,
dba_objects b,
dba_rollback_segs c,
v$transaction d,
v$session e
WHERE a.object_id = b.object_id
AND a.xidusn = c.segment_id
AND a.xidusn = d.xidusn
AND a.xidslot = d.xidslot
AND d.addr = e.taddr
/



– The following is a short script which returns the username, OS login name
– and terminal from the dynamic performance tables for any user with a lock
– on a rollback segment.


COLUMN rr HEADING ‚RB Segment‘ FORMAT a18
COLUMN us HEADING ‚Username‘ FORMAT a15
COLUMN os HEADING ‚OS User‘ FORMAT a10
COLUMN te HEADING ‚Terminal‘ FORMAT a10

SELECT r.name rr,
nvl(s.username,‚no transaction‘) us,
s.osuser os,
s.terminal te
FROM v$lock l, v$session s,v$rollname r
WHERE l.sid = s.sid(+)
AND trunc(l.id1/65536) = r.usn
AND l.type = ‚TX‘
AND l.lmode = 6
ORDER BY r.name
/



– The following script provides detailed information about rollback segments
– including: Segment Name, Owner, Tablespace, Header file and status.


COLUMN nm FORMAT a7 HEADING ‚Name‘ trunc
COLUMN ex FORMAT 999 HEADING ‚NrEx‘
COLUMN rs FORMAT a7 HEADING ‚Size‘
COLUMN init FORMAT 999,999 HEADING ‚Init‘
COLUMN next FORMAT 999,999 HEADING ‚Next‘
COLUMN mi FORMAT 999 HEADING ‚MinE‘
COLUMN ma FORMAT 999 HEADING ‚MaxE‘
COLUMN op FORMAT 99,999,999 HEADING ‚Opt size‘
COLUMN pct FORMAT 990 HEADING ‚PctI‘
COLUMN st FORMAT a4 HEADING ‚Stat‘
COLUMN sn FORMAT a15 HEADING ‚Segm Name‘
COLUMN ts FORMAT a12 HEADING ‚In TabSpace‘
COLUMN fn FORMAT a75 HEADING ‚File containing header of rbs‘
COLUMN ow FORMAT a4 HEADING ‚Ownr‘

PROMPT
PROMPT All Rollback Segments

SELECT segment_name sn,
decode(owner,‚PUBLIC‘,‚Publ‘,‚Priv‘) ow,
tablespace_name ts, name fn
FROM sys.dba_rollback_segs d,
v$datafile f
WHERE d.file_id = f.file#;

PROMPT
PROMPT Online Rollback Segments:

SELECT d.segment_name nm,
s.extents ex,
(s.rssize/1024)||‚K‘ rs,
d.initial_extent init,
d.next_extent next,
d.pct_increase pct,
d.min_extents mi,
d.max_extents ma,
optsize op,
decode(d.status,‚ONLINE‘,‚OnL‘,‚OFFLINE‘,‚OffL‘) st
FROM v$rollname n,
v$rollstat s,
sys.dba_rollback_segs d
WHERE n.usn = s.usn
AND d.segment_name = n.name(+)
/

****************************************************************
* Ende Skript *
****************************************************************

1 Like

Erklärung und Danke
Danke einmal dafür, dass ihr euch soviel Zeit für die umfangreichen Antworten genommen habt.

Leider bin ich nur einer von den armen fünzig und hab keine Möglichkeit auf dem Server irgendetwas zu machen, ich dachte mir nur da scheinbar da nichts weitergeht frage ich mal hier im Forum und leite die Antworten an die Verantwortlichen weiter.

Selbiges werde ich mal gleich machen. :smile:

Danke nochmal,
Robert