Oracle select for updateのサンプル

SQLのselect for updateのサンプルです。(Oracle)

目次

説明 select for updateとは
サンプル select for updateの挙動の確認
  select for updateにselect for updateをした場合
  ロックされていた場合はエラーにする(select for update nowait)
  ロック状態を確認するSQL

select  for updateとは

select 項目 from テーブル
where 条件
for update;
  • 選択した行に対して、他のトランザクションが更新できないようにします。
    →他のトランザクションは待ちの状態になります。
  • commitまたはrollbackをすることで、他のトランザクションは更新できるようになります。
  • 他のトランザクションは、selectで値を取得することはできます。
  • select for updateにselect for updateした場合は待ちになります。
    →nowaitで待ちを回避できます。
  • 以下は、OracleのDML操作での自動ロックのリンクです。
    https://docs.oracle.com/cd/E57425_01/121/SQLRF/ap_locks001.htm

 

select  for updateの挙動の確認

SQLコマンドラインを2つ立ち上げ、select for updateをした時の挙動の確認します。

1.行のロックを行う

1つめのSQLコマンドラインで、select文にfor updateをつけて実行します。

select * from employee
where ID = '1'
for update;

3行目のfor updateでemployeeテーブルのID=1の行をロックします。

 

2.SQLを実行してみる

2つめのSQLコマンドラインで、for updateを付けないselect文を実行してみます。

select * from employee
where ID = '1';

1つめのSQLコマンドラインのSQLと同じ条件で実行しています。
結果の取得はできます。

 

3.Updateを実行してみる

2つめのSQLコマンドラインで、update文を実行してみます。

update employee
set name = '竹田'
where ID = '1';

updateを実行した場合、実行されないままの状態になります。待ちの状態です。
反応は返ってきません。

 

.commitを実行してみる

1つめのSQLコマンドラインで、commitを実行すると、コミットが完了します。

2つめのSQLコマンドラインのupdateの更新も実行されて終了します。

update employee
set name = '竹田'
where ID = '1';
1行が更新されました。

 

select  for updateにselect  for updateをした場合

select for updateでロックを掛けた状態に対して、別のトランザクションでselect for updateした場合は、1つめのselect for updateがcommitかrollbackされるまで2つめのselect for updateは待ちの状態になります。

以下は、別のトランザクションでselect for updateした例です。

select * from employee
where ID = '1'
for update;

実行しても動かない状態になります。

 

ロックされていた場合はエラーにする(select for update nowait)

select for updateでロックを掛けた状態に対して、別のトランザクションでselect for updateに
nowaitをつけて実行した場合は以下のエラーを返します。

「ORA-00054: リソース・ビジー。NOWAITが指定されているか、タイムアウトしました」

 

以下は、nowaitをつけたときの動きです。

1.1つめのSQLコマンドラインで実行

select * from employee
where ID = '1'
for update;

select文でfor updateをつけています。

 

2.2つめのSQLコマンドラインで実行

select * from employee
where ID = '1'
for update nowait;

3行目は、nowaitをつけています。

nowaitがあるため、待ちにはならず以下のエラーが発生します。

「ORA-00054: リソース・ビジー。NOWAITが指定されているか、タイム・アウトしました。」

 

ロック状態を確認するSQL

ロックは、V$LOCKED_OBJECTテーブルで確認します。

select
OBJECT_ID
,SESSION_ID
,ORACLE_USERNAME
,OS_USER_NAME
,PROCESS
,LOCKED_MODE
from v$locked_object;

ロック状態がある場合はデータが表示されます。
systemユーザで実行しました。権限がないと実行できません。

以下は、OracleのV$LOCKED_OBJECTのリンクです。
https://docs.oracle.com/cd/E57425_01/121/REFRN/GUID-3F9F26AA-197F-4D36-939E-FAF1EFD8C0DD.htm

関連の記事

Oracle SQLコマンドラインを使用するサンプル

△上に戻る