web-dev-qa-db-ja.com

ORA-00054:リソースがビジネスであり、NOWAITが指定されているかタイムアウトが期限切れになっています

テーブルを更新すると、なぜこのデータベースエラーが発生するのですか?

1行目のエラー:ORA-00054:リソースがビジーで、NOWAITを指定して取得したか、タイムアウトになりました

156
sun

あなたのテーブルはすでに何らかのクエリによってロックされています。たとえば、「select for update」を実行し、まだコミット/ロールバックしていないため、別のselectクエリを実行したとします。クエリを実行する前にコミット/ロールバックを行います。

185
user258367

ここから ORA-00054:リソースがビジーで、NOWAITを指定して取得しています

また、SQL、ユーザー名、マシン、ポート情報を調べて、接続を保持している実際のプロセスにアクセスすることもできます。

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;
82
Abey Tom

Oracleセッションを終了してください

アクティブなセッション情報を確認するには、以下のクエリを使用してください

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;

のように殺す

alter system kill session 'SID,SERIAL#';

(例えば、alter system kill session '13,36543';)

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

49
Chan Myae Thu

この問題には非常に簡単な回避策があります。

あなたがあなたのセッションで10046トレースを実行するならば(これをグーグル...説明するには多すぎる)。 DDL操作の前に、Oracleによって次の処理が行われることがわかります。

LOCK TABLE 'TABLE_NAME'はお待ちください

そのため、他のセッションが開いているトランザクションを持っているとエラーになります。だから修正は...ドラムロールしてください。 DDLの前にあなた自身のロックを発行し、 'NO WAIT'を除外してください。

特記事項

パーティションの分割/削除を実行している場合、Oracleはパーティションをロックするだけです。 - パーティションのサブパーティションをロックするだけです。

だから...次の手順は問題を解決します。

  1. LOCK TABLE 'テーブル名'; - あなたは「待つ」でしょう(開発者はこれをハングと呼びます)。オープントランザクションとのセッションまで、コミットします。これはキューです。だからあなたの前にいくつかのセッションがあるかもしれません。しかし、あなたはエラーにならないでしょう。
  2. DDLを実行してください。あなたのDDLはNO WAITでロックをかけます。しかし、あなたのセッションはロックを獲得しました。だからあなたはいいです。
  3. DDLの自動コミットこれでロックが解除されます。

DML文は、テーブルがロックされている間は「待機」または開発者が「ハング」と呼びます。

私はこれをジョブから実行するコードで使用してパーティションを削除します。それはうまくいきます。データベースには、毎秒数百挿入の割合で挿入されています。エラーなし.

あなたが疑問に思っているならば。 11gでこれをやる。私は過去にも同様に10gでこれをしました。

15
Bob

このエラーは、リソースが使用中のときに発生します。照会に参照制約があるかどうかを確認してください。あるいは、あなたがクエリで言及したテーブルさえビジーかもしれません。彼らは他の仕事に携わっているかもしれませんが、それらは以下の問い合わせ結果に間違いなく記載されています。

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

SIDを見つけます。

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

これは、表の変更に使用されたセッション以外のセッションがDML(更新/削除/挿入)のためにロックを保持しているときに発生します。もしあなたが新しいシステムを開発しているのであれば、あなたまたはあなたのチームの誰かがupdateステートメントを発行し、あなたが大きな影響なしにセッションを終了させる可能性があります。あるいは、誰がセッションを開いているのかがわかったら、そのセッションからコミットすることもできます。

SQL管理システムにアクセスできる場合は、それを使用して問題のあるセッションを見つけます。そしておそらくそれを殺します。

あなたはv $ sessionやv $ lockなどを使うことができますが、私はあなたにそのセッションを見つけてそれを殺す方法をグーグルに勧めます。

生産システムでは、それは本当に依存しています。 Oracle 10g以前では、次のコマンドを実行できます。

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

別のセッションですが、時間がかかりすぎる場合に備えて、次の準備をしてください。

alter system kill session '....

それはあなたがどんなシステムを持っているかに依存します、古いシステムは毎回コミットしない可能性が高いです。長期にわたるロックがあるかもしれないので、それは問題です。そのため、あなたのロックは新しいロックを防ぎ、誰がいつ解放されるかを知っているロックを待ちます。だからこそ、もう片方の文を用意してください。あるいは、似たようなことを自動的に行うPLSQLスクリプトを探すこともできます。

バージョン11gでは、待ち時間を設定する新しい環境変数があります。私はそれが私が説明したものと似たようなことをすると思う。ロックの問題は解決されないことを念頭に置いてください。

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

最後に、この種のメンテナンスを行うユーザーがシステムにほとんどいなくなるまで待つのが最善の方法です。

5

私の場合、それが 私自身のセッション のうちの1つであることを確信していました - /それはブロックしていました。したがって、次のことを行っても安全でした。

  • 次のような問題のあるセッションが見つかりました。

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

    セッションは 非アクティブ でしたが、それでも何らかの理由でロックを保持していました。あなたのケースでは他の _ where _ 条件を使う必要があるかもしれないことに注意してください(例えばUSERNAMEMACHINEフィールドを試してください)。

  • 上記で取得したIDSERIAL#を使用してセッションを終了しました。

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

@thermzによって編集された: /前のオープンセッションクエリがどれもうまくいかない場合は、これを試してください。このクエリは、セッションを強制終了するときに構文エラーを回避するのに役立ちます。

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

DMLとDDLの操作が混在しているように見えます。この問題を説明している次のURLを参照してください。

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

4
Shashi

セッションを保持しているプロセスを確認して終了してください。通常の状態に戻ります。

以下のSQLはあなたのプロセスを見つけるでしょう

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;

それを殺す

ALTER SYSTEM KILL SESSION 'sid,serial#'

OR

私がオンラインで見つけたいくつかの例はインスタンスIDを必要とし、システムの強制終了セッションを変更するようです '130,620、@ 1'。

3
Mathavan John

単純にテーブルを作成するとき、私はなんとかこのエラーにぶつかった!まだ存在していないテーブルには、明らかに競合の問題はありませんでした。 CREATE TABLEステートメントには、データの入っている表を参照するCONSTRAINT fk_name FOREIGN KEY文節が含まれていました。そうしなければならなかった:

  • CREATE TABLE文からFOREIGN KEY句を削除します。
  • FK列にINDEXを作成します
  • FKを作成する
1
bwperrin

実行していた2つのスクリプトがあると、このエラーが発生しました。私は持っていました:

  • スキーマ・ユーザー・アカウント(アカウント#1)を使用して直接接続されたSQL * Plusセッション
  • 別のSQL * Plusセッションが、異なるスキーマ・ユーザー・アカウント(アカウント#2)を使用して接続していますが、最初のアカウントとしてデータベース・リンクを介して接続しています。

テーブルをドロップしてから、アカウント#1としてテーブルを作成しました。アカウント#2のセッションでテーブルを更新しました。変更をコミットしませんでした。テーブル#ドロップ/作成スクリプトをアカウント#1として再実行しました。 drop table xコマンドでエラーが発生しました。

アカウント#2のSQL * PlusセッションでCOMMIT;を実行することで解決しました。

1
vapcguy