如何使用 AWS DMS 任务迁移非 UTC 时区的 MySQL 数据库?

3 分钟阅读
0

我有一个位于非 UTC 时区的源和目标 MySQL 实例。我想使用 AWS Database Migration Service(AWS DMS)任务迁移数据库。我该如何操作?

简短描述

当您使用 MySQL 作为源时,如果源 MySQL 实例使用非 UTC 时区,则不会正确迁移时间戳数据。在内部,MySQL 时间戳列存储为 UTC。但是,当您选择日期时,MySQL 会自动将时间戳列转换为当前会话的时区。MySQL 将当前时区的 TIMESTAMP 值转换为 UTC 进行存储。然后,MySQL 将这些值从 UTC 转换回当前时区进行检索。

同样,当您将日期存储在时间戳中时,MySQL 会将 TIMESTAMP 值从当前时区转换为 UTC。然后,它将这些值从 UTC 转换回当前时区进行检索。

当您使用 AWS DMS 时,如果源和目标 MySQL 实例的时区不是 UTC,则数据可能会不一致。例如,如果您有一个在美国/太平洋地区运行的源和目标 MySQL 数据库,则不使用 UTC。因此,会捕获源中的数据,然后作为 UTC 应用于目标,这会导致数据不一致。

解决方法

要解决此问题,请在源端点 serverTimezone 中使用额外的连接属性/端点设置。然后,将该值设置为 MySQL 数据库的时区。

serverTimezone=US/Pacific

比较以下示例,一个在源端点 serverTimezone 中有一个额外的连接属性(ECA),另一个没有 ECA。

源端点中没有 ECA serverTimezone

注意:如果不使用 ECA,则可能会发现源数据库和目标数据库之间的数据不一致。

mysql>  SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| US/Pacific         | US/Pacific          |
+--------------------+---------------------+

mysql> create  table test_tz ( id int primary key,t_date timestamp);
Query OK, 0 rows affected (0.28 sec)

mysql> insert into test_tz values (10, now());
Query OK, 1 row affected (0.31 sec)

mysql> select * from test_tz;
+----+---------------------+
| id | t_date              |
+----+---------------------+
| 10 | 2022-06-27 20:50:29 |
+----+---------------------+
1 row in set (0.25 sec)

既然您已经创建了 AWS DMS 任务,迁移数据后,完整加载后将如下所示:

目标

mysql>  SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| US/Pacific         | US/Pacific          |
+--------------------+---------------------+
1 row in set (0.30 sec)

mysql> select * from test_tz;
+----+---------------------+
| id | t_date              |
+----+---------------------+
| 10 | 2022-06-28 03:50:29 |    ===> This shows timestamp in UTC in target 
+----+---------------------+
1 row in set (0.25 sec)

现在,在源数据库中执行插入。

mysql>  insert into test_tz values (11, now());
Query OK, 1 row affected (0.38 sec)

mysql> select * from test_tz;
+----+---------------------+
| id | t_date              |
+----+---------------------+
| 10 | 2022-06-27 20:50:29 |
| 11 | 2022-06-27 21:10:13 |
+----+---------------------+
2 rows in set (0.24 sec)

目标

mysql> select * from test_tz;
+----+---------------------+
| id | t_date              |
+----+---------------------+    
| 10 | 2022-06-28 03:50:29 |
| 11 | 2022-06-28 04:10:13 |    ===> This shows timestamp in UTC in target 
+----+---------------------+
2 rows in set (0.25 sec)

在源端点中使用 ECA serverTimezone=US/Pacific

完整加载后的数据:

mysql> select * from test_tz;
   +----+---------------------+
   | id | t_date              |
   +----+---------------------+
   | 10 | 2022-06-27 20:50:29 |
   | 11 | 2022-06-27 21:10:13 |
   +----+---------------------+

目标

mysql> select * from test_tz;
   +----+---------------------+
   | id | t_date              |
   +----+---------------------+
   | 10 | 2022-06-27 20:50:29 |
   | 11 | 2022-06-27 21:10:13 |
   +----+---------------------+

变更数据捕获(CDC)期间的数据

3 rows in set (0.25 sec)
+----+---------------------+
| 12 | 2022-06-28 04:12:06 |
| 11 | 2022-06-28 04:10:13 |
| 10 | 2022-06-28 03:50:29 |
+----+---------------------+
| id | t_date              |
+----+---------------------+
mysql> select * from test_tz;
mysql> 
mysql> 

Query OK, 1 row affected (0.38 sec)
mysql> insert into test_tz values (12, current_time());

目标

3 rows in set (0.25 sec)
+----+---------------------+
| 12 | 2022-06-28 04:12:06 |
| 11 | 2022-06-28 04:10:13 |
| 10 | 2022-06-28 03:50:29 |
+----+---------------------+
| id | t_date              |
+----+---------------------+
mysql> select * from test_tz;

因此,当源 MySQL 实例使用非 UTC 时区时,ECA serverTimezone 可帮助您迁移和复制时间戳数据。


AWS 官方
AWS 官方已更新 2 年前