2011-11-15 64 views
10

我們最近切換到了RDS實例,並注意到我們的一堆數據庫任務在比需要提前4小時觸發。在進一步調查時,問題是由RDS實例上的默認時區設置(UTC)造成的。由於此設置無法更改,因此我們希望在使用此數據庫實例的所有應用程序的全局代碼級別上解決問題。我嘗試用調整RDS上的默認時區設置

set GLOBAL time_zone = 'US/Eastern'" OR 
set time_zone = 'US/Eastern'" 

設置時區上的數據庫實例創建爲「美國/東方」但是,這會產生錯誤「數據庫錯誤:未知或不正確的時區:‘美國/東方’」

您認爲我在這裏做錯了什麼?有沒有人使用任何其他解決方案?

+0

這是什麼類型的數據庫? MySQL的? – Michael

回答

9

不幸的是,無法在RDS DB ParameterGroups中設置default_timezone,因此您的嘗試已經是正確的方向。

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

要設置通過設置全局你需要有未授予您作爲一個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 rver

例如,如果你使用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 = '<YOUR_DESIRED_TIMEZONE>'查詢您連接到右後您的數據庫

+4

如果您只是將'SET time_zone ='US/Eastern''更改爲'SET time_zone ='-5:00'',那麼您可以避免mySql在默認情況下在RDS中不按名稱識別時區的問題。 –

+0

好點,感謝代言。 –

+0

@RyanWeir,如果使用原始小時偏移量,請注意夏令時/夏令時等 – indivisible

3

tldr;

創建一個所有用戶都具有EXECUTE訪問權限的「共享」模式,創建一個修改會話時區並修改init_connect MySQL參數來調用它的SPROC。


瑞安威爾在他的優秀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('[email protected]' 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

+0

我只能使用user()而不是current_user()來工作,你知道爲什麼你的解決方案似乎適用於所有人,但我與current_user();奇怪的是,current_user()只是在init_connect的上下文中從命令行返回相同的東西,它實際上會返回您使用RDS創建的初始主用戶,而不管連接到MySQL的用戶如何。我通過更改過程來驗證這一點,以插入具有current_user()值的記錄; – Neo

0

@Thomas潘恩的解決方案適用於我,除了我不得不用戶user()而不是current_user()init_connect CURRENT_USER()返回主RDS用戶的上下文中。 (通過主我的意思並不是rdsadmin哪個纔是真正的根用戶,但與大多數權限數據庫實例創建的用戶。)

0

我做以便我可以更改時區

  1. 登錄到RDS並創建新參數組。

  2. 編輯新創建的參數組

  3. 設置TIME_ZONE例如:亞洲/加爾各答和保存更改

  4. 修改RDS例如,更改數據庫的參數組到新創建的參數組

  5. 保存並重新啓動RDS實例

+0

當我嘗試這個時,time_zone不是一個選項,並且default_time_zone是不可修改的...(甚至在我新創建的參數組中) - 在極光 – iewebguy

+0

@iewebguy你嘗試在DB參數組中,你應該嘗試在Cluster Parameter Group 。 –