ORACLEにタイムアウトが設定されてないので、対象テーブルのロックが解除されるまで、
ずーっと待つことになります。
アプリの不具合で、対象テーブルのロックが保持されたままになった場合、後の処理が
待ちになってしまいます。
そうならないためにも、
これから更新しようとするテーブルが既にロックされているかどうか調べてから、処理をする
ように作るのもありだと思います。
そんなとき、select * from xxx for update文を使って、更新対象テーブルがロックされてるか
確認します。
■検証
★セッションA
・テスト用テーブル作成
SQL> create table a(a number);
表が作成されました。
・テスト用データ作成
SQL> insert into a value(1);
insert into a value(1)
SQL> insert into a values(1);
1行が作成されました。
SQL> insert into a values(2);
1行が作成されました。
SQL> insert into a values(3);
1行が作成されました。
SQL> insert into a values(4);
1行が作成されました。
SQL> insert into a values(5);
1行が作成されました。
SQL> commit;
コミットが完了しました。
・テストテーブルをupdate
SQL> update a set a=1;
この時点で、テストテーブルaにロックが掛かってます。
★セッションB
別セッションで、ロック中のaテーブルを参照します。
・30秒待って、aテーブルへのロックを取得できなければ、諦める
09:31:11 SQL> select * from a for update wait 30;
select * from a for update wait 30
*
行1でエラーが発生しました。:
ORA-30006: リソース・ビジー; WAITタイムアウトの期限に達しました。
・aテーブルへのロックを取得できなければ、即諦める
09:31:43 SQL>
09:31:43 SQL> select * from a for update nowait;
select * from a for update nowait
*
行1でエラーが発生しました。:
ORA-00054: リソース・ビジー。NOWAITが指定されているか、タイムアウトしました
・aテーブルへのロックを取得できるまで待つ
SQL> select * from a for update;
※CTRL + Cで止めるまで待ってます。
その後・・・・
★セッションA
・テスト用テーブルの処理を確定し、ロック解除
SQL> rollback;
ロールバックが完了しました。
★セッションB
・テスト用テーブルのロックが解除されたので、セッションBがロックを獲得し、
テーブルaの結果が返ってくる
SQL> select * from a for update;
A
----------
1
2
3
4
5
select * from a for update;で、テーブルaがロックされます。
select * from aは、テーブルaへのロックを取得しないので、結果が返ってきます。
0 件のコメント:
コメントを投稿