RDS for OracleでOracle Schedulerのタイムゾーンを設定する

2021.06.05

しばたです。

RDS for OracleでのOracle Schedulerの設定まわりについて調査する必要があり、その結果と設定変更手順についてこの場で軽く共有します。

RDS for Oracleのタイムゾーンについて

RDS for OracleにおけるタイムゾーンはデフォルトでUTCとなっています。

オプショングループからTimeZoneオプションを設定することで、RDSのホストレベルでタイムゾーンを変更しOracleにも反映させることができます。

ただし、Oracle Schedulerが内部で持つタイムゾーン設定はこのオプションの影響を受けずUTCのままです。
これが問題となる一番わかりやすい例は自動データベース・メンテナンス・タスクで、現在サポートされているOracleの一般的な構成であれば、

  • 毎週月~金曜日の22:00開始 (4時間以内に完了)
  • 毎週土、日曜日の06:00開始 (20時間以内に完了)

にデータベースに対して統計情報の収集などのタスクを実施します。
RDS for Oracleではこの時刻がUTCになるため、日本でRDS for Oracleを使う場合にこのままだと都合が悪い場合があるかと思います。

Oracle Schedulerのタイムゾーン変更

そこで最初にOracle Schedulerのタイムゾーンを変更します。
手順は以下のドキュメントにばっちり書いてあります。

RDS for Oracleでも通常のOracleと同様にDBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTEを使うことでOracle Schedulerのタイムゾーンを変更できます。

-- 現在のOracle Schedulerタイムゾーンを確認
SELECT VALUE FROM DBA_SCHEDULER_GLOBAL_ATTRIBUTE WHERE ATTRIBUTE_NAME='DEFAULT_TIMEZONE';

-- Oracle SchedulerのデフォルトタイムゾーンをAsia/Tokyo (+09:00) に変更
EXEC DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('default_timezone','Asia/Tokyo');

-- 変更後のOracle Schedulerタイムゾーンを確認
SELECT VALUE FROM DBA_SCHEDULER_GLOBAL_ATTRIBUTE WHERE ATTRIBUTE_NAME='DEFAULT_TIMEZONE';

やってみた

今回TimeZoneオプションをAsia/TokyoにしたOracle 19c SE2(19.0.0.0.ru-2021-04.rur-2021-04.r1)環境を用意しました。

初期状態の時刻を確認してみると以下の様にSYSTIMESTAMPはJSTの時刻を返しますがOracle SchedulerはUTCの時刻を返します。

各タスクの実行予定もUTCです。

ここでDBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTEを実行してやるとOracle Schedulerのデフォルトタイムゾーンおよび各タスクの実行予定時刻が無事Asia/Tokyoに変更されました。

Oracle Schedulerタスクの時刻変更

先述の自動データベース・メンテナンス・タスクの実行時刻に対してタイムゾーンを変更するだけでなく、実行時刻やDuration自体を変えたい場合もあるでしょう。
その場合はDBMS_SCHEDULERパッケージを使い、

  1. 当該スケジュールを一旦無効に
  2. 当該スケジュールの属性変更
  3. 当該スケジュールを有効に戻す

の手順を踏む必要があります。
実行例がOracleのドキュメントにありますので詳細はそちらをご覧ください。

やってみた

前節で紹介した環境を使い月曜日のメンテナンスタスク(SYS.MONDAY_WINDOW)を変更する簡単な例を紹介します。

--
-- 月曜日のメンテナンスタスク(SYS.MONDAY_WINDOW)のスケジュールを変える例
--
DECLARE
    V_WINDOW_NAME VARCHAR2(257) := 'SYS.MONDAY_WINDOW';
BEGIN
    -- 設定変更前に無効に
    DBMS_SCHEDULER.DISABLE(name  => V_WINDOW_NAME);

    -- スケジュールの属性変更 (実行間隔) : 通常月曜 22:00 開始を 03:00 開始に変更 
    DBMS_SCHEDULER.SET_ATTRIBUTE(
        name      => V_WINDOW_NAME,
        attribute => 'REPEAT_INTERVAL',
        value     => 'freq=daily;byday=MON;byhour=3;byminute=0;bysecond=0'
    );
    -- スケジュールの属性変更 (Duration) : 通常4時間のを2時間に変更
    DBMS_SCHEDULER.SET_ATTRIBUTE(
        name      => V_WINDOW_NAME,
        attribute => 'DURATION',
        value     => NUMTODSINTERVAL(2, 'hour')
    );

    -- 設定変更後有効に
    DBMS_SCHEDULER.ENABLE(name => V_WINDOW_NAME);
END;
/

月曜日の次回実行時刻が無事更新されました。

余談 : rdsadmin_util.alter_db_time_zone について

RDS for Oracleでタイムゾーンに関わる設定には最初に紹介したTimeZoneオプション以外にRDSの管理パッケージにあるrdsadmin_util.alter_db_time_zoneプロシージャも存在します。

rdsadmin_util.alter_db_time_zoneプロシージャはドキュメントに

alter_db_time_zone プロシージャは、特定のデータ型のみのタイムゾーンを変更し、SYSDATE は変更しません。タイムゾーンの設定に関する他の制限については、Oracle ドキュメントに示されています。

とある様に特定のデータ型向けの様でOracle Schedulerのタイムゾーンには影響を及ぼしませんでした。

調べてみたもののrdsadmin_util.alter_db_time_zoneプロシージャはDBTIMEZONEを変更するのは確認できたのですが、それ以外にどこに影響するのかは正直わかりませんでした。
DBTIMEZONEも原則変更するものではないですし、rdsadmin_util.alter_db_time_zoneプロシージャは本当に必要に迫られた場合以外は使わない方が良さそうに思えました。

最後に

以上となります。

今回はテスト環境で試してますので気軽にタイムゾーンやスケジュールを変えていますが、本番環境で実施する際は既存のタスクへの影響 *1を考慮し変更タイミングを念入りに調整する必要があるでしょう。

Oracleのタイムゾーン設定は地味に複雑で分かりにくいところがありますが、本記事の内容が役に立てば幸いです。

脚注

  1. 時刻変更により実行してほしいタスクがスキップされてしまわないか、など