Amazon RDS(MySQL)でTimezoneを変更する
ども、大瀧です。
RDSにするか、DB on EC2にするかを検討する際によく挙がるのが、Timezoneをどうするかという話。AWSのサービスは基本的にはUTC(世界標準時)で提供され、RDSも例外ではありません。
「世界展開を狙うサービスであれば当然UTCで!」となるのですが、既存システムをAWSに移行する案件などでは「アプリの改修ができないので、移行前とTimezoneを合わせたい」ケースが多いと思います。
EC2であれば、OSのTimezone設定をちょちょいと変えるだけで対応できるのですが、RDSは直接インスタンスにログインできないため、ちょっとした工夫と注意が必要です。
概要
今回はRDS MySQLを対象に、Timezoneを変更する方法をご紹介します。
RDSでユーザーに提供される"Masterユーザー"は、MySQLのrootユーザーとは異なりSUPER権限(管理者権限)を持っていません。そのため、TimezoneをSET GLOBALコマンドで設定することはできません。その代わり、"クライアントがRDSに接続するときに自動実行するコマンド"を指定するinit_connectというパラメータにSET SESSIONコマンドでTimezoneの変更を設定できます。RDSにinit_connectパラメータを設定するためには、Parameter Groupを利用します。で、そのときの注意点が2つあります。
- rdsadminというユーザーはAWS側からDBインスタンスを管理するために使用されるらしく、timezoneをいじるのはまずそうなので除外する
- init_connectパラメータに直接コマンドを投入するとうまく動かないので、ストアドプロシージャを定義し、CALL文で呼び出すようにする
というわけで、それなりに面倒な手順になりましたが(汗)、以下の通り設定します。
- ストアドプロシージャの作成
- Parameter Groupの作成
- RDSにParameter Groupを設定
- DBインスタンスの再起動
ちなみにRDS Oracleの場合は、専用のストアドプロシージャが用意されているので、そちらを使用します。
Appendix: Common DBA Tasks for Oracle - Amazon Relational Database Service → "Setting the Database Time Zone"
1. ストアドプロシージャの作成
まずは、設定するRDSにMasterユーザーでログインし、ストアドプロシージャshared.store_time_zoneを定義します。sharedスキーマは、各ユーザーがアクセスできる任意のスキーマとして作成しているので、実際に使用するスキーマ名およびデータベース名と重複しなければ何でもいいと思います。
今回は日本標準時(Asia/Tokyo)にしてみます。
mysql> CREATE DATABASE shared; Query OK, 1 row affected (0.01 sec) mysql> DELIMITER | mysql> CREATE PROCEDURE shared.`store_time_zone`() -> IF NOT (POSITION('rdsadmin@' IN CURRENT_USER()) = 1) THEN -> SET SESSION time_zone = 'Asia/Tokyo'; -> END IF | Query OK, 0 rows affected (0.01 sec) mysql> DELIMITER ;
念のため、設定したストアドプロシージャshared.`store_time_zone`の動作を確認します。
mysql> select now(); +---------------------+ | now() | +---------------------+ | 2013-08-01 08:25:59 | +---------------------+ 1 row in set (0.02 sec) mysql> CALL shared.store_time_zone; Query OK, 0 rows affected (0.10 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2013-08-01 17:26:08 | +---------------------+ 1 row in set (0.02 sec) mysql>
日本標準時(UTCより9時間進む)になっていることが確認できました!
2. Parameter Groupの作成
RDSでは、MySQLのパラメータをParameter Groupとしてグループ単位で管理します。デフォルトのパラメータグループは変更できないため、パラメータグループを新規作成します。作成時に、ストアドプロシージャがRDSへの接続時に自動実行されるよう、init_connectパラメータにストアドプロシージャの呼び出しを設定します。
対応するMySQLのバージョンを選択します。グループ名、説明は任意の内容でOKです。
続いて、作成したグループの設定を編集します。
たくさんのパラメータの中(アルファベット順)からinit_connectパラメータを探し、以下のCALL文を入力します。
CALL shared.store_time_zone
設定の保存ボタンは、画面の上部にあります。スクロールし、Save Changesをクリックして、設定完了です。
3. RDSにParameter Groupを設定
DBインスタンスのParameter Groupを、新規作成したものに変更します。
Parameter Groupを作成したグループに変更し、Apply Immediatelyのチェックをオンにし、変更します。
4. DBインスタンスの再起動
DBインスタンスを再起動して、動作を確認します。しばらくかかるので、お茶でも飲んでいましょう。DBインスタンスのStatus列がavailableになれば、再起動完了です。
mysql> select now(); +---------------------+ | now() | +---------------------+ | 2013-08-01 17:45:21 | +---------------------+ 1 row in set (0.02 sec)
ちゃんとTimezoneの設定が反映されています!
まとめ
RDSの制約により多少手間はかかりますが、任意のTimezoneでRDSを使用することができました。RDSは、Multi AZや自動バックアップなどの強力な管理機能を安価に利用できる、クラウドならではのコンポーネントです。少しでも多くのAWSシステムで、RDSが有効に活用されるといいですね。