小ネタ/AWS DMS(CDC)で MySQL to MySQL 移行時のタイムゾーン指定
AWS の DMS(CDC)でソース・ターゲットの両方が MySQL(RDS / Aurora MySQL)の場合、タイムゾーンの指定に注意が必要です。
前提
- DMS 3.4.7 を使用
- ソース・ターゲット各 MySQL サーバのタイムゾーン(
time_zone)が正しく設定されている
元の設定がずれている(例:サーバのtime_zone設定がUTCのまま、タイムゾーンを無視してAsia/Tokyoの日時値を保存している)場合は違う状況になります。
ポイント
- AWS DMS(Data Migration Service)の CDC(Change Data Capture)で MySQL(RDS / Aurora MySQL を含む)から MySQL(同)にデータをレプリケーションで移行するときは、 ソースエンドポイントのタイムゾーンを設定しない
理由
MySQL では、内部的に
-
TIMESTAMP型の日時は1970-01-01 00:00:01.000000以降のUTC日時 -
DATETIME型の日時はタイムゾーンを持たない日時
を保持します。
一方、DMS ではどちらもデフォルトで DMS データ型DATETIMEにマッピングされます。
この状況でソースエンドポイントのタイムゾーンとしてUTC以外、例えばAsia/Tokyoを選んで DB に接続したときに、DMS が TIMESTAMP型の値をUTCではなくローカルタイムゾーンの日時値として処理してしまう ようです。つまり、ソース側をUTC以外にしてしまうとTIMESTAMP型の値がずれます。
DATETIME型の値はタイムゾーンを持たず、ソースエンドポイントのタイムゾーンに関わらずそのままの値が移行されます。
結果として、TIMESTAMP型もDATETIME型もタイムゾーンがずれないようにするには、ソースエンドポイントのタイムゾーンをUTC(デフォルトのまま)にしておくのが良いことになります。
ターゲットエンドポイントについては、デフォルト(UTC)のままでもAsia/Tokyoなどを指定しても問題ない模様ですが、特に理由がなければデフォルトのままにしておきます。
別の方法
TIMESTAMP型の列を DMS の文字列型にマッピングすれば、ソースタイムゾーンをUTC以外(Asia/Tokyoなど)にした場合でも正しく移行できるようです。
ただ、DMS のSTRING型を使うには全体の桁数(文字数)の指定(型の後ろにカッコで表記)が必要ですが(指定しないとエラーになります)、TIMESTAMP型における桁数指定は「秒未満の部分の桁数」となり意味が違うので、STRING型ではなくCLOB型を指定するのが良さそうです。
Discussion