News
DBA-Tipp: ORA-00054 - Administrative Arbeiten trotzdem erzwingen

Die Information ist ein schnelllebiges Gut. Jeden Tag werden wir mit hunderten Informationen zugemüllt. Deshalb sind wir bestrebt uns auf das Wesentliche zu konzentrieren und nur substantiell nachhaltige Informationen bereitzustellen.

Icon Unternehmen

Zuweilen fallen administrative Aufgaben an, die theoretisch im laufenden Betrieb möglich wären, praktisch aber in einer hoch frequentierten Datenbank scheitern. Weil der entsprechende Befehl den erforderlichen Lock am Zielobjekt nicht sofort platzieren kann, bricht er mit einem ORA-00054 ab. Typischerweise sind davon DDL-Befehle, wie zum Beispiel

  • alter table … drop column ...
  • create index ...
  • drop index …

usw. betroffen.

Trotzdem gibt es keinen Grund, den DDL-Befehl nun verzweifelt immer und immer wieder zu wiederholen oder die Wartung in eine „ruhigere“ Zeit zu verlegen. Grund für das Scheitern des DDL und für den ORA-00054 ist die Tatsache, dass die DDL-Operation implizit NOWAIT ausgeführt wird. Kann der erforderliche Lock also nicht sofort platzieren werden, was in einem stark beschäftigten System sehr wahrscheinlich ist, bricht der Versuch unmittelbar ab. Wie die Fehlermeldung

resource busy and acquire with NOWAIT specified or timeout expired

bereits vermuten lässt, kann die gewünschte Operation jedoch mit einem Timer versehen werden. Um diesen NOWAIT-Modus zu umgehen, kennt die Oracle Datenbank seit Version 11.1 den Sessionparameter.

ddl_lock_timeout

Dieser ist – aus unerfindlichen Gründen – per Default auf 0 gesetzt. Timeouts sind einstellbar in Sekundeneinheiten von 1 bis 1.000.000, wobei letzteres synonym für unlimitiertes Warten steht.

Folgendes Beispiel zur Illustration der Funktionsweise:
Wir definieren eine Testtabelle mit zwei Spalten ...

SQL> CREATE TABLE foo(
  2     column1 integer,
  3     column2 integer
  4  );

Table created.

… und „simulieren“ eine hohe Last, indem wir dort eine Zeile einfügen, diese allerdings nicht committen.

SQL high_load_session> INSERT INTO foo (column1) values (0);

1 row created.

SQL high_load_session>

Die Testtabelle ist nun aufgrund der laufenden Transaktion gegen DDL gesperrt. Der Versuch, die Spalte column2 zu löschen, schlägt folglich mit einem ORA-00054 fehl.

SQL admin_session> ALTER TABLE foo DROP COLUMN column2;
ALTER TABLE foo DROP COLUMN column2
            *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired


SQL admin_session>

Im Gegensatz dazu wird die selbe Operation bei einem gesetzten Lock-Timeout in die Lock-Queue eingereiht und hat damit gute Chancen, rechtzeitig vor Ablauf des Timers durchzulaufen.

SQL admin_session> ALTER SESSION SET ddl_lock_timeout=60;

Session altered.

SQL admin_session> ALTER TABLE foo DROP COLUMN column2;
...


SQL high_load_session> commit;

Commit complete.

SQL high_load_session>
 

...
Table altered.

SQL admin_session>