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を実行した場合、実行されないままの状態になります。待ちの状態です。
反応は返ってきません。
4.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
関連の記事