話題の記事

Amazon RDS(MySQL)でTimezoneを変更する

2013.08.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。
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文で呼び出すようにする

というわけで、それなりに面倒な手順になりましたが(汗)、以下の通り設定します。

  1. ストアドプロシージャの作成
  2. Parameter Groupの作成
  3. RDSにParameter Groupを設定
  4. 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パラメータにストアドプロシージャの呼び出しを設定します。

rds_timezone01

対応するMySQLのバージョンを選択します。グループ名、説明は任意の内容でOKです。

rds_timezone02

続いて、作成したグループの設定を編集します。

rds_timezone03

たくさんのパラメータの中(アルファベット順)からinit_connectパラメータを探し、以下のCALL文を入力します。

CALL shared.store_time_zone

rds_timezone04

設定の保存ボタンは、画面の上部にあります。スクロールし、Save Changesをクリックして、設定完了です。

rds_timezone05

3. RDSにParameter Groupを設定

DBインスタンスのParameter Groupを、新規作成したものに変更します。

rds_timezone06

Parameter Groupを作成したグループに変更し、Apply Immediatelyのチェックをオンにし、変更します。

rds_timezone07

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が有効に活用されるといいですね。

参考