テーブルを更新すると、なぜこのようなデータベースエラーが発生するのですか?
1行目でエラーが発生しました: ORA-00054: リソースがビジーで、NOWAITを指定して取得するか、タイムアウトが切れました。
テーブルが何らかのクエリによって既にロックされています。例えば、"select for update"を実行し、まだコミット/ロールバックしておらず、別のselectクエリを実行している可能性があります。クエリを実行する前にコミット/ロールバックを行ってください。
また、sql,username,machine,port情報を調べて、接続を保持している実際のプロセスにアクセスすることもできます。
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;
オラクルのセッションを殺してください。
以下のクエリを使用して、アクティブなセッション情報を確認します。
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#';
(たとえば、「システムキルセッション '13,36543'を変更する」;)。
参照。 http://abeytom.blogspot.com/2012/08/finding-and-fixing-ora-00054-resource.html。
この問題については、非常に簡単な作業があります。
セッションで10046トレースを実行した場合(Google this。.. 説明するには多すぎる)。 DDL操作の前に、Oracleが次のことを行うことがわかります。
ロックテーブル 'TABLE_NAME'いいえ。
したがって、別のセッションで開いているトランザクションがある場合、エラーが発生します。 だから修正はです。.. ドラムロールしてください。 DDLの前に独自のロックを発行し、「NO WAIT」を除外します。
特別注記:
分割/ドロップパーティションを実行している場合、oracleはパーティションをロックするだけです。 -パーティションのサブパーティションをロックするだけです。
そう。.. 次の手順で問題が解決します。
1。 ロックテーブル「テーブル名」; -あなたは「待つ」でしょう(開発者はこれを絞首刑と呼びます)。 開いているトランザクションのセッションまで、コミットします。 これはキューです。 だからあなたの前にいくつかのセッションがあるかもしれません。 しかし、あなたはエラーを出しません。 2。 DDLを実行します。その後、DDLはNO WAITでロックを実行します。ただし、セッションによってロックが取得されました。 だからあなたは元気です。 3。 DDLオートコミット。 これによりロックが解放されます。
DMLステートメントは「待機」するか、テーブルがロックされている間、開発者が「ハング」と呼びます。
これは、ジョブからドロップパーティションまで実行されるコードで使用します。 うまくいきます。 これは、数百の挿入/秒の割合で常に挿入されているデータベースにあります。 エラーはありません。
あなたが疑問に思っているなら。 これを11gで行います。 私はこれを以前も10gで行ったことがあります。
このエラーは、リソースがビジーの場合に発生します。 クエリに参照制約があるかどうかを確認します。 または、クエリで言及したテーブルでもビジーになる可能性があります。 彼らは、次のクエリ結果に確実にリストされる他の仕事に従事している可能性があります。
SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'
SIDを見つけます。
SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
私の場合、ブロックされているのは自分のセッションの1つであると確信していました。 したがって、次のことを行うのは安全でした。
*私は次の問題セッションを見つけました。
SELECT * FROM V $ SESSION WHERE OSUSER = 'my_local_username';
。
セッションは非アクティブでしたが、それでもどういうわけかロックを保持していました。 ケースでは、他のどこの状態を使用する必要がある場合があります(例:. USERNAME
または MACHINE
フィールドを試してください)。
*上記で取得した「ID」と「SERIAL#」を使用してセッションを殺しました。
alter system kill session '< id>、< serial#>';
;
@thermzによる編集:以前のオープンセッションクエリのいずれも機能しない場合は、これを試してください。 このクエリは、セッションを殺している間、構文エラーを回避するのに役立ちます。
これは、テーブルの変更に使用されたセッション以外のセッションが、DML(更新/削除/挿入)が原因である可能性が高いロックを保持している場合に発生します。 新しいシステムを開発している場合、あなたまたはあなたのチームの誰かが更新ステートメントを発行し、あまり影響を与えずにセッションを殺すことができる可能性があります。 または、セッションを開いている人がわかったら、そのセッションからコミットすることもできます。
SQL管理システムにアクセスできる場合は、それを使用して問題のあるセッションを見つけます。 そしておそらくそれを殺します。
v $ sessionやv $ lockなどを使用できますが、そのセッションを見つける方法とそれを殺す方法をググることをお勧めします。
生産システムでは、それは本当に異なります。 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);
最後に、この種のメンテナンスを行うユーザーがシステムに少なくなるまで待つことをお勧めします。
セッションを保持しているプロセスを確認し、それを殺します。 正常に戻ります。
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'を変更します。
実行していたスクリプトが2つあるときに、このエラーが発生しました。 私が持っていた:
-スキーマユーザーアカウント(アカウント#1)を使用して直接接続されたSQL プラスセッション。 -別のSQL Plusセッションは、別のスキーマユーザーアカウント(アカウント#2)を使用して接続されていますが、最初のアカウントとしてデータベースリンクを介して接続しています。
テーブルドロップを実行し、アカウント#1としてテーブルを作成しました。
アカウント#2のセッションでテーブルの更新を実行しました。 変更をコミットしませんでした。
アカウント#1としてテーブルドロップ/作成スクリプトを再実行しました。 drop table x
コマンドでエラーが発生しました。
アカウント#2のSQL * Plusセッションで「COMMIT;」を実行して解決しました。
<。!-スニペットを開始:js hide:false console:true babel:false -->。
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#';
<。!-終了スニペット-->。