sql >> データベース >  >> RDS >> Oracle

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

    ORA-00054:リソースがビジーで、NOWAITを指定して取得 Oracleデータベースで見られる一般的なエラーです

    参照:Oracleドキュメント

    これは通常、トランザクションによってロックされているテーブルでDDLを実行しようとしたときに発生します。また、selectforupdateステートメントがNOWAITオプションを使用して実行された場合にも発生します

    SQL> alter table emp add (middlename varchar2(15));
    *
    ERROR at line 1:
    ORA-00054: resource busy and acquire with NOWAIT specified
    
    SQL> create index  emp_idx on emp(emp_no);
    
    *
    ERROR at line 1:
    ORA-00054: resource busy and acquire with NOWAIT specified
    
    SQL> Select * from emp for update NOWAIT;
    
    *
    ERROR at line 1:
    ORA-00054: resource busy and acquire with NOWAIT specified
    

    ORA-00054エラーを防ぐ方法

    1.メンテナンスウィンドウでDDLを実行するか、トランザクションが実行されていないピーク時間外に実行します

    2. 11gの場合、DDL_LOCK_TIMEOUTがあります

    これは、DDLロックを待機する時間を指定するだけです

    SQL> alter session set ddl_lock_timeout = 600;
    Session altered.
    
    SQL> alter table emp add (middlename varchar2(15));
    
    Table Altered
    

    3.オラクルロックを保持しているトランザクションを強制終了して続行できます

    column sid_ser format a12 heading 'session,|serial#'; 
    column username format a12 heading 'os user/|db user'; 
    column process format a9 heading 'os|process'; 
    column spid format a7 heading 'trace|number'; 
    column owner_object format a35 heading 'owner.object'; 
    column locked_mode format a13 heading 'locked|mode'; 
    column status format a8 heading 'status'; 
    select 
        substr(to_char(l.session_id)||','||to_char(s.serial#),1,12) sid_ser, 
        substr(l.os_user_name||'/'||l.oracle_username,1,12) username, 
        l.process, 
        p.spid, 
        substr(o.owner||'.'||o.object_name,1,35) owner_object, 
        decode(l.locked_mode, 
                 1,'No Lock', 
                 2,'Row Share', 
                 3,'Row Exclusive', 
                 4,'Share', 
                 5,'Share Row Excl', 
                 6,'Exclusive',null) locked_mode, 
        substr(s.status,1,8) status 
    from 
        v$locked_object l, 
        all_objects     o, 
        v$session       s, 
        v$process       p 
    where 
        l.object_id = o.object_id 
    and l.session_id = s.sid 
    and s.paddr      = p.addr 
    and s.status != 'KILLED'
    /
    

    ブロッキングセッションを見つけてOracleセッションを強制終了することを決定したら、以下のクエリを使用して強制終了セッションSQLを生成できます

    select 'alter system kill session '''||sid||','||serial#||''';' from v$session where sid=&1;
    

    4. ORA-00054:リソースがビジーで、NOWAITを指定して取得する 申し込みフォームで、以下のように進めます

    ORA-00054:リソースがビジーで、アプリケーションフォームで指定されたNOWAITで取得する場合があります。この場合、アプリケーションはロックを待機しないため、ロックを見つけるのが非常に困難になります。これは通常、アプリケーションの問題が待機オプションなしで更新を選択した場合に発生します。セッションがロックを待機しているときに、dba_waitersを介してロックを見つけることができます。nowaitセッションでロックされているため、それを見つけることはできません。

    セッションのoraclesqlトレースを見つけて、問題を再現する必要があります。トレースが利用可能になったら。トレースファイルでerr=54を探す必要があります

    PARSING IN CURSOR #18446744071497070208 len=167 dep=1 uid=173 oct=3 lid=173 tim=3315832569154 hv=817497356 ad='31afc8bcd0' sqlid='6gvfwr8sbn18c'
    SELECT GROUP_MARK_ID FROM MTL_INV_SERIAL_NUMBERS WHERE CURRENT_ORGANIZATION_ID = :B3 AND INVENTORY_ITEM_ID = :B2 AND SERIAL_NUMBER = :B1 FOR UPDATE OF GROUP_MARK_ID NOWAIT
    END OF STMT
    PARSE #18446744071497070208:c=53,e=52,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1906360410,tim=3315832569152
    BINDS #18446744071497070208:
    Bind#0
    oacdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
    oacflg=03 fl2=1206001 frm=00 csi=00 siz=80 off=0
    kxsbbbfp=ffffffff7c203028 bln=22  avl=03  flg=05
    value=23
    Bind#1
    oacdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
    oacflg=03 fl2=1206001 frm=00 csi=00 siz=0 off=24
    xsbbbfp=ffffffff7c203040 bln=22  avl=05  flg=01
    value=11111
    Bind#2
    oacdty=01 mxl=32(30) mxlc=00 mal=00 scl=00 pre=00
    oacflg=03 fl2=1206001 frm=01 csi=871 siz=0 off=48
    kxsbbbfp=ffffffff7c203058 bln=32  avl=08  flg=01
    value="1222333"
    EXEC #18446744071497070208:c=1167,e=1167,p=0,cr=9,cu=1,mis=0,r=0,dep=1,og=1,plh=1906360410,tim=3315832570599
    ERROR #18446744071497070208:err=54 tim=3315832570735
    STAT #18446744071497070208 id=1 cnt=0 pid=0 pos=1 obj=0 op='FOR UPDATE  (cr=0 pr=0 pw=0 time=0 us)'
    

    エラーを示す行と上記の部分は、エラーを発生させているステートメントを示しています

    SELECT GROUP_MARK_ID FROM MTL_INV_SERIAL_NUMBERS WHERE CURRENT_ORGANIZATION_ID = :B3 AND INVENTORY_ITEM_ID = :B2 AND SERIAL_NUMBER = :B1 FOR UPDATE OF GROUP_MARK_ID NOWAIT
    

    次に、ブロッキングセッションを見つけるために、NOWAITオプションを使用してsqlplusでステートメントを起動する必要があります

    SELECT GROUP_MARK_ID FROM MTL_INV_SERIAL_NUMBERS WHERE CURRENT_ORGANIZATION_ID = :B3 AND INVENTORY_ITEM_ID = :B2 AND SERIAL_NUMBER = :B1 FOR UPDATE OF GROUP_MARK_ID ;
    

    その後、このセッションは待機し、dba_waitersからブロッキングセッションを簡単に見つけて、ブロッキングセッションを強制終了できます。

    5. Oracle11gおよびOracle12cを使用すると、エラーORA-00054

    を中断することなくオンラインで実行できる多くのDDLアクティビティがあります。
    SQL> create index  emp_idx on emp(emp_no) online;
    

    12c以降では、DROP INDEX、DROP CONSTRAINT、ALTER INDEX UNUSABLE、およびSETCOLUMNUNUSEDコマンドでONLINEキーワードを使用できます

    関連記事

    ORA-00942テーブルまたはビューが存在しません
    ORA-28000アカウントがロックされています
    ORA-28002
    ORA-00904:識別子が無効です
    ORA-01017:ユーザー名/パスワードが無効です。ログオンが拒否されました
    システム強制終了セッションの変更


    1. SQL ServerでのDATEADD()の例

    2. コマンドラインからMySQLに接続する方法

    3. JPA大文字のテーブル名

    4. 1つの列の値を複数の列の値に分割する