ロックを強制的に解除する方法について
ロックを強制的に解除する (Oracle)
悪いセッションがレコードをロックして,そのまま動かなくなったため,
他のセッションがそのロック待ちの状態になってシステムが停止してしまう,
ということは,よくあります.
この文書では,その状況の対策について,自分自身では未検証の方法を含めて記述しています.
ALTER SYSTEM KILL SESSION
最も標準的な対処療法.
v$sessionからロックを保持しているプロセスを探して,そいつのsidとserial#を求め,
その値を使って
SQL> alter system kill session 'sid, serial#';
を実行する.
私の場合は,こんな感じのSQLを実行しています.
SQL> select sid, serial#, username, machine, osuser, program, status,
'alter system kill session ''' || sid || ',' || serial# || ''';' sql
from v$session
where username is not null;
すると,ALTER SYSTEM文の形でつらつらと出力されてきますので,
ここから該当する行を選んでコピーし,実行すればOK.
しかしこの方法は,毎回DBA(管理者)の関与が必要なのが難点.
EXPIRE_TIME
これは,私は使ったことがない方法ですが,
クライアントは切断したのに,サーバ側でのプロセスが残ってしまってロックをつかんでいる,
などという状況への対応というか,予防策です.
TCP/IPのkeep alive機能を利用して,無効になった接続を自動的に切断する機能.
sqlnet.oraに
を記述する.nは,無効になってから切断するまでの時間(分).推奨は10.
これを使うと,サーバーからクライアントへ定期的にプローブパケットを送信して,
接続が無効かどうかの確認を行い,無効なら接続切断とプロセス終了処理を行う.
WindowsNTではOSの仕様上,最大値は16に制限されており,
また,keepaliveを利用しているため,TCP/IPの設定によっては正常に作動しないこともあるらしい.
で,問題なのが,これを設定した環境でALTER SYSTEM KILL SESSIONを行うと,
killedしたセッションがshutdown immediateを行わない限り,
いつまでたっても消えないという情報がある.(設定しない場合は,2時間で消える.
2時間とはTCP/IPのkeep alive設定のデフォルト)
ということで,あまり積極的には推奨できません.
プロファイルを使用する
これは,ロックをつかんでいる接続が非アクティブという前提での対策ですが,
プロファイルを使って切断を行う方法です.
ユーザにプロファイルを割り当てることで,
アイドル時間の長いセッションを自動的に切断できる.
SQL> CREATE PROFILE prof1 LIMIT IDLE_TIME 30;
SQL> ALTER USER SCOTT PROFILE prof1;
接続が,30分以上非アクティブであれば切断する.
この方法も,私自身は未検証です.
そういえば確か,IBMのDB2(UDB)だと,ロックタイムアウトなんてのがあるんだな.
興味深い.