调整 RDS 上的默认时区设置

Posted

技术标签:

【中文标题】调整 RDS 上的默认时区设置【英文标题】:Adjusting for the default time-zone setting on RDS 【发布时间】:2011-12-29 18:31:48 【问题描述】:

我们最近切换到一个 RDS 实例,并注意到我们的大量数据库任务比需要提前 4 小时触发。进一步调查后,该问题是由 RDS 实例上的默认时区设置 (UTC) 引起的。由于此设置无法更改,我们希望在使用此数据库实例的所有应用程序中全局解决代码级别的问题。我尝试使用

将我创建的数据库实例上的时区设置为“美国/东部”
set GLOBAL time_zone = 'US/Eastern'" OR
set time_zone = 'US/Eastern'"

但这会产生错误“数据库错误:未知或不正确的时区:'US/Eastern'”

你认为我在这里做错了什么?有人用过其他解决方案吗?

【问题讨论】:

这是什么类型的数据库? mysql 【参考方案1】:

很遗憾,无法在 RDS DB ParameterGroups 中设置 default_timezone,因此您的尝试已经是正确的方向。

$ rds-describe-db-parameters default | grep "time_zone"
DBPARAMETER  default_time_zone                                                                   engine-default  string   static   false

要通过 SET GLOBAL 设置全局值,您需要拥有作为 RDS 用户未授予您的 SUPER 权限。

设置 time_zone 的唯一方法是基于每个连接

mysql> SET time_zone = timezone;

在我的机器上,我成功地尝试了美国/东部,但我运行的是相当老的一代。

要确定您可以使用的时区,请登录您的框

mysql -h yourboxhost.rds.amazonaws.com -u <youruser> -p

然后输入

mysql> SELECT * FROM mysql.time_zone_name;

您应该获得可以在您的实例上设置的已安装和有效时区名称的列表

+----------------------------------------+--------------+
| Name                                   | Time_zone_id |
+----------------------------------------+--------------+
| Africa/Abidjan                         |            1 |
| Africa/Accra                           |            2 |
| Africa/Addis_Ababa                     |            3 |
| Africa/Algiers                         |            4 |
| Africa/Asmara                          |            5 |
| Africa/Asmera                          |            6 |
| Africa/Bamako                          |            7 |
| Africa/Bangui                          |            8 |
| Africa/Banjul                          |            9 |
| Africa/Bissau                          |           10 |
| Africa/Blantyre                        |           11 |
| Africa/Brazzaville                     |           12 |
| Africa/Bujumbura                       |           13 |
| Africa/Cairo                           |           14 |
etc...

每次连接到数据库服务器时都必须设置 time_zone

例如,如果您使用 php Mysqli 扩展,您可以这样做

$mysqli = mysqli_init();
mysqli_options($mysqli,MYSQLI_INIT_COMMAND,"SET time_zone = 'Africa/Brazzaville'" );
mysqli_real_connect($mysqli,$host, $user, $pass,$dbName) or die ('Unable to connect');

否则,只需手动(就让您的数据库连接器执行此操作)在您连接到数据库后立即执行 SET time_zone = '&lt;YOUR_DESIRED_TIMEZONE&gt;' 查询

【讨论】:

如果你只是把SET time_zone = 'US/Eastern'改成SET time_zone = '-5:00',那么你就可以避免mySql在RDS中默认不识别时区的问题。 @RyanWeir,如果您使用原始小时偏移量,请注意夏令时/夏令时等【参考方案2】:

现在可以修改RDS数据库实例的time_zone设置:https://aws.amazon.com/de/premiumsupport/knowledge-center/rds-change-time-zone/

【讨论】:

重要的是要注意这个必须在集群参数组上修改(至少对于aurora mysql)。 DB参数组只有default_time_zone不可修改。【参考方案3】:

tldr;

创建一个所有用户都可以执行的“共享”架构,创建一个修改会话时区的 SPROC,并修改 init_connect MySQL 参数以调用它。


正如 Ryan Weir 在其出色的 answer in a duplicate question 中指出的那样,如果可能的话,应该避免这种情况。但是,如果您像我一样,为了方便和理智而想要实现它,那么我采用了 Ryan 的解决方案并进行了一些修改。

如果您在 MySQL 中设置了多个具有不同权限的用户,那么简单地将 sproc 放入 mysql 架构中可能会出现问题。为了解决这个问题,我创建了一个名为“shared”的新模式,并为我的所有用户提供了对该模式的 EXECUTE 访问权限。然后我创建了以下存储过程。

DROP PROCEDURE IF EXISTS shared.store_time_zone;
CREATE PROCEDURE shared.`store_time_zone`()
IF NOT (POSITION('rdsadmin@' IN CURRENT_USER()) = 1) THEN     
    SET SESSION time_zone = 'US/Pacific';  
END IF;

我更喜欢设置“美国/太平洋”来处理夏令时,但您应该对此进行测试以确保您的 MySQL 实例首先识别它。只需执行以下查询SET SESSION time_zone = 'US/Pacific'; 以确保它正常工作。要查找您的时区,请执行 SELECT * FROM mysql.time_zone_name;

此时,我建议您在修改参数组之前测试权限,并可能破坏所有内容。只需连接到数据库(最好使用具有低级别权限和/或常用的用户)并执行以下查询。

CALL shared.store_time_zone;
select now();

希望您没有收到任何错误,并且出现了正确的时间。

接下来,您需要修改您的 RDS 实例正在使用的数据库参数组中的 init_connect 参数。您可以通过 API 或命令行实用程序在 RDS Web 控制台中执行此操作。如果您使用命令行,它将如下所示:

$ rds-modify-db-parameter-group PARAMGROUP --parameters "name=init_connect, value='CALL shared.store_time_zone', method=immediate"

如果您通过 Web 控制台执行此操作,则只需更改 init_connect 的值。

CALL shared.store_time_zone

在 Web 控制台中返回您的 RDS 实例并将详细信息窗格向下滚动到数据库参数组。它应该说类似(应用)或(同步)。一旦它(同步)去测试一切以确保没有问题。

如果此时您遇到问题并需要回滚,那么我建议将 init_connect 值设置为无害的值,例如:

SET SESSION time_zone = '-00:00';

无法通过 Web 控制台将其设置回空白。有关为什么can't restore the empty value for the DB parameter 的更多详细信息,请参阅此线程

【讨论】:

我只能使用 user() 而不是 current_user() 来解决这个问题,你知道为什么你的解决方案似乎对我以外的所有人都适用 current_user();奇怪的是 current_user() 仅在 init_connect 的上下文中从命令行返回相同的内容,它实际上返回您使用 RDS 创建的初始主用户,而不管连接到 MySQL 的用户。我通过更改过程以插入具有 current_user() 值的记录来验证这一点;【参考方案4】:

我做了以下步骤,以便我可以更改时区

    登录 RDS 并创建新参数组。

    编辑新创建的参数组

    设置时区,例如:亚洲/加尔各答并保存更改

    修改RDS实例,将DB的Parameter Group改为新建的参数组

    保存并重启 RDS 实例

【讨论】:

当我尝试这个时,time_zone 不是一个选项,并且 default_time_zone 是不可修改的......(即使在我新创建的参数组中) - 在极光中 @iewebguy 您正在数据库参数组中尝试,您应该在集群参数组中尝试。 这确实有效,但实际上我必须编辑集群,而不是它在步骤 4 中的实例【参考方案5】:

@Thomas Paine 的解决方案对我有用,除了我必须使用 user() 而不是 current_user() 因为在 init_connect current_user() 的上下文中返回主 RDS 用户。 (我所说的 master 并不是指真正的 root 用户 rdsadmin,而是使用具有大多数权限的数据库实例创建的用户。)

【讨论】:

以上是关于调整 RDS 上的默认时区设置的主要内容,如果未能解决你的问题,请参考以下文章

docker容器里设置中文时区

手机时间怎么调整?

如何为 AWS RDS 实例设置数据库时区 [重复]

Highcharts上的时区

如何在 Flatpickr 中将给定时区设置为默认时区而不是系统时区?

django 默认时区设置