222

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

1行目のエラー:ORA-00054:リソースがビジーで、NOWAITが指定されているか、タイムアウトが期限切れになっています。

4

15 に答える 15

256

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

于 2011-01-30T12:02:20.877 に答える
115

ここから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;
于 2012-08-10T03:29:24.090 に答える
74

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

于 2014-02-10T11:01:08.063 に答える
16

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

セッションで10046トレースを実行する場合(グーグルこれ...説明するには多すぎます)。DDL操作の前に、Oracleが次のことを行うことがわかります。

LOCK TABLE'TABLE_NAME' NO WAIT

したがって、別のセッションに開いているトランザクションがある場合、エラーが発生します。修正は...ドラムロールをお願いします。DDLの前に独自のロックを発行し、「NOWAIT」を省略します。

特記事項:

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

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

  1. LOCKTABLE'テーブル名'; -あなたは「待つ」でしょう(開発者はこれをぶら下げと呼びます)。開いているトランザクションとのセッションがコミットされるまで。これはキューです。そのため、あなたの前にいくつかのセッションがあるかもしれません。ただし、エラーは発生しません。
  2. DDLを実行します。その後、DDLはNOWAITでロックを実行します。ただし、セッションはロックを取得しています。だからあなたは良いです。
  3. DDLは自動コミットします。これにより、ロックが解放されます。

DMLステートメントは、テーブルがロックされている間、「待機」するか、開発者が「ハング」と呼ぶようになります。

これを、ジョブから実行してパーティションを削除するコードで使用します。正常に動作します。これは、毎秒数百回の速度で絶えず挿入されているデータベースにあります。エラーはありません。

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

于 2013-04-29T21:15:21.750 に答える
14

このエラーは、リソースがビジーのときに発生します。クエリに参照制約があるかどうかを確認します。または、クエリで言及したテーブルでさえビジーである可能性があります。彼らは、次のクエリ結果に確実にリストされる他の仕事に従事している可能性があります。

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

SIDを見つけて

SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
于 2013-07-15T08:28:43.457 に答える
12

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

  • 私は次のような問題のあるセッションを見つけました:

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

    セッションは非アクティブでしたが、それでも何らかの形でロックを保持していました。場合によっては、他のWHERE条件(tryUSERNAMEMACHINEfieldsなど)を使用する必要がある場合があることに注意してください。

  • 上記を使用してセッションを強制終了し、上記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'
于 2013-09-03T10:27:07.337 に答える
9

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

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);

最後に、この種のメンテナンスを行うユーザーがシステムに少なくなるまで待つのが最善かもしれません。

于 2013-07-15T19:49:57.587 に答える
8

select
   c.owner,
   c.object_name,
   c.object_type,
   b.sid,
   b.serial#,
   b.status,
   b.osuser,
   b.machine
from
   v$locked_object a,
   v$session b,
   dba_objects c
where
   b.sid = a.session_id
and
   a.object_id = c.object_id;
   
   ALTER SYSTEM KILL SESSION 'sid,serial#';

于 2019-09-26T17:52:14.570 に答える
5

セッションを保持しているプロセスを確認して、それを強制終了します。通常に戻ります。

以下の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#'

また

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

于 2014-11-27T03:30:13.377 に答える
5

他の回答で述べたように、このエラーは他のセッションで実行されている同時DML操作が原因で発生します。これにより、OracleはデフォルトのNOWAITオプションを使用してDDLのテーブルをロックできなくなります。

データベースに管理者権限がない場合、または他のセッションを強制終了/中断できない場合は、DDL操作の前に次のコマンドを使用することもできます。

alter session set DDL_LOCK_TIMEOUT = 30;
--Run your DDL command, e.g.: alter table, etc.

バックグラウンドジョブが大規模な挿入/更新操作を実行しているデータベースでこのエラーを繰り返し受け取り、セッションでこのパラメーターを変更すると、ロックを数秒待った後もDDLを続行できました。

詳細については、この回答に関するrshdevのコメント、oracle - baseのこのエントリ、またはDDL_LOCK_TIMEOUTの公式ドキュメントを参照してください

于 2021-08-27T18:40:45.243 に答える
4

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

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

于 2011-05-05T12:37:43.097 に答える
4

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

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

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

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

于 2017-05-23T19:46:27.480 に答える
3

テーブルを作成するだけで、なんとかこのエラーが発生しました。まだ存在していないテーブルでは、明らかに競合の問題はありませんでした。このCREATE TABLEステートメントには、CONSTRAINT fk_name FOREIGN KEY人口の多いテーブルを参照する句が含まれていました。そうしなければならなかった:

  • CREATETABLEステートメントからFOREIGNKEY句を削除します
  • FK列にINDEXを作成します
  • FKを作成する
于 2015-11-19T15:05:58.603 に答える
-3

私も同様の問題に直面しています。このエラーを解決するためにプログラマーがする必要はありません。OracleDBAチームに通知しました。彼らはセッションを殺し、魅力のように働きました。

于 2017-01-17T20:50:27.127 に答える
-8

Shashiのリンクによって提供される解決策が最善です...dbaまたは他の誰かに連絡する必要はありません

バックアップを作成する

create table xxxx_backup as select * from xxxx;

すべての行を削除します

delete from xxxx;
commit;

バックアップを挿入します。

insert into xxxx (select * from xxxx_backup);
commit;
于 2013-03-27T09:23:41.707 に答える