PL/SQL でスリープ(処理の待機)する
PL/SQL にて処理を一時停止するには DBMS_LOCK パッケージを使用する。
Oracle 18c 以降は別途権限付与がいらない DBMS_LOCK.SLEEP を使用する。
古いバージョンのオラクルでは長時間連続してスリープさせるとスリープ明けまで shutdown immediate が待機してしまうので注意が必要。
同様に Oracle 11g より前の ALTER SYSTEM KILL SESSION IMMEDIATE では SLEEP 待機中はセッションを直ちに切断できない。
DBMS_LOCK パッケージを使用するための準備 (Oracle 12c 以前)
DBMS_LOCK は PUBLIC ロールに含まれていないため、別途実行権限を付与する必要がある。
DBMS_LOCK パッケージの実行権限を GRANT する例
SQL> CONN / AS SYSDBA
SQL> GRANT EXECUTE ON DBMS_LOCK TO RIVUS ;
Oracle 18c 以降は DBMS_LOCK.SLEEP は非推奨 となり DBMS_SESSION.SLEEP を代用するので権限付与作業は不要。
SLEEP もセッションを占有することでインパクトがあるが、DBMS_LOCK の他のプロシージャも相当なものなので歓迎できる変更。
DBMS_LOCK.SLEEP / DBMS_SESSION.SLEEP を使い n秒間待機する
DBMS_LOCK.SLEEP / DBMS_SESSION.SLEEP ともに秒数を指定し、0.01 が最小単位となる。つまり100分の1秒の精度。
10 秒スリープする
Oracle 12c まで
SQL> set timing on
SQL> execute DBMS_LOCK.SLEEP(10);
PL/SQLプロシージャが正常に完了しました。
経過: 00:00:10.15
Oracle 18c 以降
SQL> execute DBMS_SESSION.SLEEP(10);
PL/SQLプロシージャが正常に完了しました。
ループ処理の内部で 0.5 秒間待機する
0.5 秒のスリープを 10回行なう
SQL> begin
2 for i in 1..10 loop
3 dbms_output.put_line(to_char(systimestamp, 'mi:ss.ff3'));
4 DBMS_LOCK.SLEEP(0.5); -- DBMS_SESSION.SLEEP (Oracle 18c)
5 end loop;
6 end ;
7 /
38:17.829
38:18.329
38:18.830
38:19.331
38:19.831
38:20.332
38:20.833
38:21.334
38:21.834
38:22.335
PL/SQLプロシージャが正常に完了しました。
経過: 00:00:05.03
DBMS_LOCK 関連事項