Oracle Cloudのデータベースサービス(DBシステム)のプロビジョンでのタイムゾーンの選択

####概要
2020年3月からOracle Cloudのデータベースサービス(DBシステム)をプロビジョニングする際に、タイムゾーンを選択できるようになりました。その前はタイムゾーンがUTCの設定でのプロビジョニングしかありませんでした。

[Time zone selection for bare metal and virtual machine DB systems](https://docs.cloud.oracle.com/en-us/iaas/releasenotes/changes/d7e2bf9d-22ca-4e06-b5ba-00976ed8c047/)

本記事では、このプロビジョニング時のタイムゾーンの選択の手順と、それによりどこが変わったのか説明します。タイムゾーンの設定、といってもOS,Oracle DBそれぞれでいくつか確認ポイントがありそうなので、それぞれがどのような設定になっているか、ひとまず確認できたことをお伝えします。

プロビジョニング時のタイムゾーンの選択しても、Pluggable DatabaseのSchedulerのタイムゾーンはUTCのままになっている、という事象が確認できたので、その点に関して対応策も含めて記載しています。

なお、以前よりプロビジョニングの後にタイムゾーンの設定を変更することは可能で、それに関しては上記のURLの記事の中でリンクが紹介されています。本記事の「参考情報」でも紹介します。

2020年3月ごろの情報・環境を元に本記事は記載しています。

####DBシステムのプロビジョニングでのタイムゾーン選択
DBシステムのプロビジョニングでタイムゾーンを選択する方法は、とても簡単です。Oracle Cloudのコンソール画面から、通常のプロビジョニングと同じように「DBシステムの作成」ボタンをクリックして、プロビジョニングのための設定を入力する画面を表示させます。最初の画面の下部に「拡張オプションの表示」があるのでクリックします。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368742/d2f5592f-3fd3-afd9-9084-05311d6e62e6.png)

すると次の図のようなタイムゾーンの設定箇所が表示されます。デフォルトはUTCになっています。ここの例では、ブラウザを日本語環境に設定しているので「Asia/Tokyo」が表示され、選択できるようになっています。表示されてないタイムゾーンに関しては「別のタイム・ゾーンの選択」を選択すると選べるようになります。

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368742/39257687-2ea6-0fac-96e0-74dd9c72b932.png)

残りの設定は通常のDBシステムと同じように設定していき、プロビジョニングします。通常のDBシステムのプロビジョニングに関しては、下記の記事が参考になります。

[クラウドでOracle Databaseを使う - Oracle Cloud Infrastructureを使ってみよう](https://community.oracle.com/docs/DOC-1019568)

####DBシステムのLinuxの設定を確認する
先に挙げた例のように、DBシステムのプロビジョニングの際にタイムゾーンの設定を「Asia/Tokyo」にしたVMにログインして、OSに関してどのように設定されているか確認してみます。

```
[opc@oracledb ~]$ date
Wed Mar 11 19:12:42 JST 2020
```
オプションなしのdateコマンドで日本時間で出力されます。（UTCでプロビジョニングした場合は、UTCになっています。）
システムクロックのローカルタイムを決める /etc/localtime に関して確認してみます。

```
[opc@oracledb ~]$ strings /etc/localtime
TZif2
TZif2
JST-9
```
日本時間になるように /etc/localtime が設定されていることがわかります。（UTCでプロビジョニングした場合は、ここがUTCに設定されています。）
ハードウェアクロックの設定になる /etc/sysconfig/clock を確認してみます。

```
[opc@oracledb ~]$ cat /etc/sysconfig/clock
ZONE="America/Los_Angeles"
UTC=true
ARC=false
```
この設定は日本時間になっていません。ここはUTCでプロビジョニングした場合と同じです。いろいろ参考ドキュメントを読むと「ここの設定がAsia/Tokyoになっていないと再起動時にUTCに戻るかも」と思ったりもしたのですが、試した限りでは、そのようなことはありませんでした。
timedatectlは下記のように出力されます。

```
[opc@oracledb ~]$ timedatectl
      Local time: Wed 2020-03-11 19:34:08 JST
  Universal time: Wed 2020-03-11 10:34:08 UTC
        RTC time: Wed 2020-03-11 10:34:08
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
```


とりあえず上記のような設定になっていました、ということで。下記の記事などを参考にしています。
[Linuxのタイムゾーンまわり CentOS7編](https://qiita.com/szly/items/dcc67c85689725795c26)

####DBシステムのOracle Databaseの設定を確認する
続けて、プロビジョニングの際にタイムゾーンの設定を「Asia/Tokyo」にしたVMで、Oracle Databaseに関してどのように設定されているか確認してみます。
ここの例では、ストレージの管理に「Oracle Grid Infrastructure」（つまりASM）を選択しているので、その設定から確認します。

/u01/app/19.0.0.0/grid/crs/install/s_crsconfig_"node_name"_env.txt というファイルを確認します。下記のようになっていました。（ファイルの上部は省略しています）

```
TZ=Asia/Tokyo
NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
CRS_LIMIT_STACK=2048
CRS_LIMIT_OPENFILE=65536
CRS_LIMIT_NPROC=65536
TNS_ADMIN=
```
タイムゾーンの設定がAsia/Tokyoになっていることがわかります。（UTCでプロビジョニングした場合は、ここが```TZ=UTC```となっています。）

続けて、SQL*PlusからOracle Databaseに接続してSYSTIMESTAMPの出力を確認してみます。

```sql
SQL> SELECT SYSTIMESTAMP FROM dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
11-MAR-20 07.52.42.894832 PM +09:00
```
デフォルトで日本時間で表示されます。**これはOracle Databaseの設定ではなく、OSの設定（システムクロック）に依存しています。**UTCでプロビジョニングした場合は、ここがUTCで出力されます。

Oracle Databaseに関するタイムゾーンとして、データベースを作成した時点の設定に依存する```dbtimezone```があります。これを確認してみます。

```sql
SQL> SELECT dbtimezone FROM dual;

DBTIME
------
+00:00
```

**Oracle Databaseに関しては、特にタイムゾーンは設定されていません。**この点に関しては、「そもそもOracle Databaseに設定されている（埋め込まれている）タイムゾーンの設定とは何に使われるのか」ということとあわせて理解するとよいです。
下記はデータベースのタイムゾーンの設定に関するマニュアルへのリンクです。

[Oracle Database Databaseグローバリゼーション・サポート・ガイド 19c - 4.9 データベースのタイム・ゾーンの設定](https://docs.oracle.com/cd/F19136_01/nlspg/datetime-data-types-and-time-zone-support.html#GUID-2AF15A96-CD19-4074-8DE6-17BAD0D7DF37)

ここに下記のような記載があります。

*データベースのタイム・ゾーンが関連するのは、TIMESTAMP WITH LOCAL TIME ZONE列のみです。データベース間でのデータ転送時にデータ変換を回避してパフォーマンスを改善するために、データベースのタイム・ゾーンはUTCに設定することをお薦めします。これは、分散データベース、レプリケーションおよびエクスポートとインポートには特に重要です。*

TIMESTAMP WITH LOCAL TIME ZONE型の列への動作にしか影響はないから、データベースのタイムゾーンはUTCの設定のままでいいじゃないか、という感じの説明です。
Oracle Databaseに設定されているタイムゾーンを、データベース作成後に変更するには、上記のマニュアルにあるように、

```ALTER DATABASE SET TIME_ZONE='+09:00';```

のように実行します。データベースの再起動が必要です。また、TIMESTAMP WITH LOCAL TIME ZONE列を持つ表がありデータが格納されている場合は、データベースのタイムゾーンの変更はできません。

とりあえずこのような設定になっていました、ということで。下記の記事が参考になります。

[日付データ演算の達人技を伝授する 【第3話】](https://www.atmarkit.co.jp/ait/articles/0505/27/news116_2.html)

####Schedulerのタイムゾーン

最初に本記事をアップした際はチェックできてなかったのですが、下記の記事により、**Oracle DatabaseのSchedulerのタイムゾーンが、(Asia/Tokyoでプロビジョニングしても)Pluggable Database(PDB)はUTCのままである**、という注意点があることがわかりました(2020/3時点)。

[[Oracle Cloud] DBaaS (VM) を使ってみる その3 - DBaaS使うときに確認しておいたほうがよいとこ](https://qiita.com/NSO-KC/items/e24f40b420fb9a20f43d)

本記事を作成した環境でも確認してみました。

```sql
SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT
<- 最初はCDB$ROOTのSchedulerのタイムゾーンを確認します
SQL> select dbms_scheduler.stime from dual;

STIME
---------------------------------------------------------------------------
16-MAR-20 07.25.26.808519000 PM ASIA/TOKYO
<- CDB$ROOTのSchedulerのタイムゾーンはAsia/Tokyoになっています。

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB1                           READ WRITE NO
<- 本環境ではプロビジョニング時にPDB1というPluggable Databaseを作成しています。

SQL> alter session set container=pdb1;

Session altered.

SQL> select dbms_scheduler.stime from dual;

STIME
---------------------------------------------------------------------------
16-MAR-20 10.26.07.651614000 AM ETC/UTC
<- PDB1のSchedulerのタイムゾーンはUTCになっています。
```

このようにCDB$ROOTのSchedulerのタイムゾーンはAsia/Tokyoになっているのに、プロビジョニング時に作成されているPluggable DatabaseではUTCになってしまっています。```DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE```で修正することが可能です。

```sql
SQL> exec DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('default_timezone','Asia/Tokyo');

PL/SQL procedure successfully completed.

SQL> select dbms_scheduler.stime from dual;

STIME
---------------------------------------------------------------------------
16-MAR-20 07.40.54.388685000 PM ASIA/TOKYO
```


Schedulerのタイムゾーンに関しては、下記が参考になります。

[Oracle DBの日時データ型とタイムゾーン](https://qiita.com/tpusuke/items/c424fe771cd973d5299e)

####参考情報
DBシステムのプロビジョニング後に、タイムゾーンの設定を変える手順に関しては、下記のドキュメントが参考になります。

[DB System Time Zone](https://docs.cloud.oracle.com/en-us/iaas/Content/Database/References/timezones.htm)
この中の手順をそのまま実行すると、本記事で紹介した「タイムゾーンを選択してDBシステムをプロビジョンしたVMのLinux,Oracle Database」と同じ環境になるわけではありません。
OSに関しては、/etc/sysconfig/clock でUTCから変更する手順が記載されています。Oracle Databaseに関してはデータベースのタイムゾーンの変更方法が記載されています。
それぞれ不要なケースも考えられますので、本記事で紹介した内容などを確認の上で実施するかしないか判断するとよいと思います。