it-swarm.com.de

ORA-00054: Ressource belegt und mit angegebenem NOWAIT abgerufen oder Zeitlimit abgelaufen

Warum erhalte ich diesen Datenbankfehler, wenn ich eine Tabelle aktualisiere?

FEHLER in Zeile 1: ORA-00054: Ressource belegt und mit angegebenem NOWAIT abgerufen oder Timeout abgelaufen

165
sun

Ihre Tabelle ist bereits durch eine Abfrage gesperrt. Beispielsweise haben Sie möglicherweise "select for update" ausgeführt und noch keine weitere Auswahlabfrage festgeschrieben/rückgängig gemacht und ausgelöst. Führen Sie ein Commit/Rollback durch, bevor Sie Ihre Abfrage ausführen.

194
user258367

von hier ORA-00054: Ressource belegt und mit angegebenem NOWAIT beschaffen

Sie können auch die SQL-Adresse, den Benutzernamen, den Computer und die Port-Informationen abrufen und den tatsächlichen Prozess abrufen, der die Verbindung hält

SELECT O.OBJECT_NAME, S.SID, S.SERIAL#, P.SPID, S.PROGRAM,S.USERNAME,
S.MACHINE,S.PORT , S.LOGON_TIME,SQ.SQL_FULLTEXT 
FROM V$LOCKED_OBJECT L, DBA_OBJECTS O, V$SESSION S, 
V$PROCESS P, V$SQL SQ 
WHERE L.OBJECT_ID = O.OBJECT_ID 
AND L.SESSION_ID = S.SID AND S.PADDR = P.ADDR 
AND S.SQL_ADDRESS = SQ.ADDRESS;
89
Abey Tom

Bitte beenden Sie die Oracle-Sitzung

Verwenden Sie die folgende Abfrage, um die aktiven Sitzungsinformationen zu überprüfen

SELECT
    O.OBJECT_NAME,
    S.SID,
    S.SERIAL#,
    P.SPID,
    S.PROGRAM,
    SQ.SQL_FULLTEXT,
    S.LOGON_TIME
FROM
    V$LOCKED_OBJECT L,
    DBA_OBJECTS O,
    V$SESSION S,
    V$PROCESS P,
    V$SQL SQ
WHERE
    L.OBJECT_ID = O.OBJECT_ID
    AND L.SESSION_ID = S.SID
    AND S.PADDR = P.ADDR
    AND S.SQL_ADDRESS = SQ.ADDRESS;

wie töten

alter system kill session 'SID,SERIAL#';

(Zum Beispiel alter system kill session '13,36543';)

Referenz http://abeytom.blogspot.com/2012/08/finding-and-fixing-ora-00054-resource.html

53
Chan Myae Thu

Es gibt eine sehr einfache Lösung für dieses Problem.

Wenn Sie in Ihrer Sitzung einen 10046-Trace ausführen (googeln Sie dies ... zu viel, um es zu erklären). Sie werden feststellen, dass Oracle vor jeder DDL-Operation Folgendes ausführt:

LOCK TABLE 'TABLE_NAME' NO WAIT

Wenn also eine andere Sitzung eine offene Transaktion hat, wird eine Fehlermeldung angezeigt. Das Problem ist also ... Trommelwirbel bitte. Stellen Sie Ihre eigene Sperre vor der DDL aus und lassen Sie das "NO WAIT" weg.

Spezielle Notiz:

wenn Sie Partitionen teilen/löschen, sperrt Oracle die Partition. - So können Sie nur die Partitionsunterpartition sperren.

Also ... Die folgenden Schritte beheben das Problem.

  1. SPERRTABELLE 'TABELLENNAME'; - Sie werden "warten" (Entwickler nennen dies hängen). Commit bis zur Sitzung mit der offenen Transaktion. Dies ist eine Warteschlange. Es können also mehrere Sitzungen vor Ihnen liegen. aber du wirst KEINEN Fehler machen.
  2. Führen Sie DDL aus. Ihre DDL führt dann eine Sperre mit dem Wert NO WAIT aus. Ihre Sitzung hat jedoch die Sperre erlangt. Du bist also gut.
  3. DDL führt automatische Festschreibungen durch. Dadurch werden die Sperren freigegeben.

DML-Anweisungen warten oder werden von Entwicklern als "hängen" bezeichnet, während die Tabelle gesperrt ist.

Ich verwende dies in Code, der von einem Job ausgeführt wird, um Partitionen zu löschen. Es funktioniert gut. Es befindet sich in einer Datenbank, die ständig mit einer Geschwindigkeit von mehreren hundert Einfügungen pro Sekunde eingefügt wird. Keine Fehler.

wenn du dich fragst. Tun Sie dies in 11g. Ich habe das schon in der Vergangenheit in 10g gemacht.

16
Bob

Dieser Fehler tritt auf, wenn die Ressource ausgelastet ist. Überprüfen Sie, ob die Abfrage referenzielle Einschränkungen enthält. Oder sogar die Tabellen, die Sie in der Abfrage erwähnt haben, sind ausgelastet. Sie sind möglicherweise mit einem anderen Job beschäftigt, der in den folgenden Abfrageergebnissen definitiv aufgeführt wird:

SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'

Finden Sie die SID,

SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
10

In meinem Fall war ich mir ziemlich sicher, dass es eine von meine eigenen Sitzungen war, die blockierte. Daher war es sicher, Folgendes zu tun:

  • Ich fand die beleidigende Sitzung mit:

    SELECT * FROM V$SESSION WHERE OSUSER='my_local_username';

    Die Sitzung war inaktiv, hielt aber trotzdem irgendwie die Sperre. Beachten Sie, dass Sie möglicherweise andere WOBEI Bedingungen in Ihrem Fall verwenden müssen (z. B. versuchen Sie USERNAME oder MACHINE Felder ).

  • Beendete die Sitzung mit dem oben erworbenen ID und SERIAL#:

    alter system kill session '<id>, <serial#>';

Bearbeitet von @thermz: Wenn keine der vorherigen offenen Abfragen funktioniert, probieren Sie diese aus. Diese Abfrage kann Ihnen helfen, Syntaxfehler beim Beenden von Sitzungen zu vermeiden:

  • SELECT 'ALTER SYSTEM KILL SESSION '''||SID||','||SERIAL#||''' immediate;' FROM V$SESSION WHERE OSUSER='my_local_username_on_OS'
7
wrygiel

Dies ist der Fall, wenn eine andere Sitzung als die zum Ändern einer Tabelle verwendete aufgrund einer DML (Aktualisieren/Löschen/Einfügen) eine Sperre aufweist. Wenn Sie ein neues System entwickeln, ist es wahrscheinlich, dass Sie oder jemand in Ihrem Team die Update-Anweisung herausgibt und Sie die Sitzung ohne große Konsequenzen beenden können. Oder Sie können von dieser Sitzung aus einen Commit durchführen, sobald Sie wissen, wer die Sitzung geöffnet hat.

Wenn Sie Zugriff auf ein SQL-Administrationssystem haben, verwenden Sie dieses, um die fehlerhafte Sitzung zu finden. Und vielleicht töte es.

Sie könnten v $ session und v $ lock und andere verwenden, aber ich schlage vor, Sie googeln, wie Sie diese Sitzung finden und dann beenden.

In einem Produktionssystem kommt es wirklich darauf an. Für Oracle 10g und älter können Sie ausführen

LOCK TABLE mytable in exclusive mode;
alter table mytable modify mycolumn varchar2(5);

Halten Sie in einer separaten Sitzung jedoch Folgendes bereit, falls dies zu lange dauert.

alter system kill session '....

Es hängt davon ab, über welches System Sie verfügen. Ältere Systeme werden mit größerer Wahrscheinlichkeit nicht jedes Mal ein Commit ausführen. Dies ist ein Problem, da möglicherweise lange bestehende Schlösser vorhanden sind. So würde Ihre Sperre alle neuen Sperren verhindern und auf eine Sperre warten, die weiß, wann sie freigegeben wird. Deshalb haben Sie die andere Aussage bereit. Sie können auch nach PLSQL-Skripten suchen, die ähnliche Aktionen automatisch ausführen.

In Version 11g gibt es eine neue Umgebungsvariable, die eine Wartezeit festlegt. Ich denke, es macht wahrscheinlich etwas Ähnliches wie ich beschrieben habe. Wohlgemerkt, dass Sperrprobleme nicht verschwinden.

ALTER SYSTEM SET ddl_lock_timeout=20;
alter table mytable modify mycolumn varchar2(5);

Schließlich ist es möglicherweise am besten zu warten, bis sich nur noch wenige Benutzer im System befinden, die diese Art von Wartung durchführen.

6

Ihr Problem sieht so aus, als würden Sie DML- und DDL-Operationen mischen. Siehe diese URL, die dieses Problem erklärt:

http://www.orafaq.com/forum/t/54714/2/

4
Shashi

Überprüfen Sie einfach, ob der Prozess die Sitzung hält, und beenden Sie sie. Es ist wieder normal.

Unter SQL finden Sie Ihren Prozess

SELECT s.inst_id,
   s.sid,
   s.serial#,
   p.spid,
   s.username,
   s.program FROM   gv$session s
   JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id;

Dann töte es

ALTER SYSTEM KILL SESSION 'sid,serial#'

OR

ein Beispiel, das ich online gefunden habe, scheint auch die Instanz-ID zu benötigen.

4
Mathavan John

Ich habe es geschafft, diesen Fehler zu finden, wenn ich einfach eine Tabelle erstellt habe! Es gab offensichtlich kein Konfliktproblem auf einem Tisch, der noch nicht existierte. Die CREATE TABLE -Anweisung enthielt eine CONSTRAINT fk_name FOREIGN KEY -Klausel, die auf eine gut gefüllte Tabelle verweist. Ich musste:

  • Entfernen Sie die FOREIGN KEY-Klausel aus der CREATE TABLE-Anweisung
  • Erstellen Sie einen INDEX in der FK-Spalte
  • Erstellen Sie die FK
3
bwperrin

Ich hatte diesen Fehler, als ich 2 Skripte hatte, die ich laufen ließ. Ich hatte:

  • Eine SQL * Plus-Sitzung, die direkt über ein Schema-Benutzerkonto (Konto 1) verbunden ist
  • Eine andere SQL * Plus-Sitzung wurde unter Verwendung eines anderen Schema-Benutzerkontos (Konto 2) verbunden, wobei jedoch als erstes Konto eine Verbindung über eine Datenbankverbindung hergestellt wurde

Ich ließ eine Tabelle fallen, dann Tabellenerstellung als Konto # 1. Ich habe eine Tabellenaktualisierung für die Sitzung von Konto 2 durchgeführt. Änderungen nicht festgeschrieben. Führen Sie das Skript zum Löschen/Erstellen von Tabellen als Konto 1 erneut aus. Beim Befehl drop table x ist ein Fehler aufgetreten.

Ich habe es gelöst, indem ich COMMIT; in der SQL * Plus-Sitzung von Konto 2 ausgeführt habe.

3
vapcguy