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 関連事項

日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ Oracle のライセンスがわからない…
Oracle Direct (ネットで聞いても最後はここで要確認)