小ネタ/AWS DMS(CDC)で MySQL to MySQL 移行時のタイムゾーン指定

2022/07/20に公開

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型を指定するのが良さそうです。

GitHubで編集を提案

Discussion