最近总是遇到奇葩的问题...
客户的生产环境为一套两节点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
srvctl getenv listener -l--这里一般listener
-- If you are on 11.1 or lower, then use 'getenv nodeapps' instead of 'getenv listener' :
srvctl getenv nodeapps -n-- get the ASM env
srvctl getenv asm
用上面的语句检查发现集群没有配置环境变量.
既然集群没有配置启动环境变量,那我们来配置一下吧,让集群启动的时候使用我们指定的TZ来启动监听和数据库:
使用root修改:
srvctl setenv database -d
-t 'TZ= Asia/Shanghai>'
srvctl setenv listener -l-t 'TZ=Asia/Shanghai'
-- If you are on 11.1 or lower, then use 'setenv nodeapps' instead of 'setenv listener':
srvctl setenv nodeapps -n-t 'TZ=Asia/Shanghai>'
修改完成之后,重启服务器,数据库自动启动后也恢复正常.
到最后我也没弄明白,出问题的时候集群启动的时候读取的是哪里的时区信息.
不过oracle也是直接提供了setenv参数,管你系统环境是啥,我在集群里面设置一下,以后启动都是以集群配置为准,还是很方便的