記錄一次奇怪的sysdate時間錯誤問題

最近總是遇到奇葩的問題...

客戶的生產環境爲一套兩節點RAC,數據庫版本爲11.2.0.4,運行在centos6.9虛擬機中,現在發現下面客戶端連接到數據庫的時候,當會話連接在節點1上的時候,查詢的sysdate時間不對,比正常時間晚了13個小時,而當會話連接到節點2的時候,時間是正常的.

對於此問題,第一反應就是兩個系統的時區不對.連接到節點上,分別執行date命令查看,發現時區都是對的,都是CST時區,即上海時區.

使用sqlplus登錄到數據庫,分別執行查詢:

select sysdate from dual;

 發現結果都是正確的.時間一致.

檢查操作系統時區:

cat /etc/localtime

 發現也是一致的.

只能求助一下MOS,一般這種詭異的問題MOS上基本都有解決辦法,確實MOS沒有讓我們失望,找到一篇文檔:

單擊此項可添加到收藏夾   How to Diagnose Wrong Time ( SYSDATE and SYSTIMESTAMP) After DST Change , Server Reboot , Database Restart or Installation When Connecting to a Database on an Unix Server (文檔 ID 1627439.1)

 

這篇文章寫的還是很詳細的.基本上主要還是說環境變量,時區對系統時間的影響.

裏面談到了爲何用sqlplus查詢是正確的,但是通過監聽查詢卻是錯誤的:

- PMON only reads the OS environment variables when the database is started. If TZ is changed after the database is started PMON will not pick up the changed value.

也就是說PMON啓動的時候只讀取數據庫啓動時刻的操作系統環境變量,如果你後面TZ變量變化了PMO並不會變.

所以我懷疑還是時區的問題,也就是數據庫啓動時刻的系統時區不對.

執行下面的查詢查看數據庫最近啓動時刻的時區:

conn / as sysdba
SET SPACE 1 LINESIZE 80 PAGES 1000
SELECT * FROM (
select to_char(ORIGINATING_TIMESTAMP,'YYYY/MM/DD HH24:MI:SS TZH:TZM') 
from V$DIAG_ALERT_EXT 
WHERE trim(COMPONENT_ID)='rdbms' 
and MESSAGE_TEXT like ('PMON started with%') 
order by originating_timestamp desc ) 
WHERE rownum < 20;

結果發現節點1最近一次啓動時刻的時區爲-5,而節點2最近一次啓動時刻的時區是+8,兩者相差了13小時,這也是爲什麼節點1時間比節點2時間晚13小時的原因.

嘗試手工export TZ環境變量,然後重啓數據庫發現可以恢復正常:

export TZ=Asia/Shanghai

那說明確實是時區的影響導致.那麼數據庫啓動的時候讀取的系統的時區,那麼系統的時區在哪裏配置呢?在操作系統上一頓操作,什麼設置/etc/profile  ~/.bash_profile  /etc/localtime 都配置了一遍,但是還是不行.每次重啓服務器,數據庫重啓之後時區又還是-05

那麼繼續按照MOS上面的進行檢查,是否是集羣做了配置導致的,查看集羣的啓動環境變量:

srvctl getenv database -d <dbname>
srvctl getenv listener -l <listenername>       --這裏一般listener

-- If you are on 11.1 or lower, then use 'getenv nodeapps' instead of 'getenv listener' :
srvctl getenv nodeapps -n <nodename>

-- get the ASM env
srvctl getenv asm

用上面的語句檢查發現集羣沒有配置環境變量.

既然集羣沒有配置啓動環境變量,那我們來配置一下吧,讓集羣啓動的時候使用我們指定的TZ來啓動監聽和數據庫:

使用root修改:

srvctl setenv database -d <dbname> -t 'TZ= Asia/Shanghai>'
srvctl setenv listener -l <listenername> -t 'TZ=Asia/Shanghai'

-- If you are on 11.1 or lower, then use 'setenv nodeapps' instead of 'setenv listener':
srvctl setenv nodeapps -n <nodename> -t 'TZ=Asia/Shanghai>'

修改完成之後,重啓服務器,數據庫自動啓動後也恢復正常.

到最後我也沒弄明白,出問題的時候集羣啓動的時候讀取的是哪裏的時區信息.

不過oracle也是直接提供了setenv參數,管你係統環境是啥,我在集羣裏面設置一下,以後啓動都是以集羣配置爲準,還是很方便的

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章