今天系统部发来一个问题,现场数据库的sysdate查询的时间,与数据库服务器的时间差13小时.于是怀疑是时区设置问题。要求现场分别在数据库服务器和应用服务器上执行sql语句
select TZ_OFFSET('PRC'),
CURRENT_DATE,
CURRENT_TIMESTAMP,
LOCALTIMESTAMP,
DBTIMEZONE,
SESSIONTIMEZONE,
SYSTIMESTAMP,
SYSDATE
from dual;
返回结果如下:
服务器 --------------------------------------------------------------------------------------------------
数据库服务器
TZ_OFFSET('PRC'): +08:00
CURRENT_DATE: 2010-12-28 12:51
CURRENT_TIMESTAMP:28-12月-10 12.51.57.593000 下午 +08:00
LOCALTIMESTAMP: 28-12月-10 12.51.57.593000 下午
DBTIMEZONE: -07:00
SESSIONTIMEZONE: +08:00
SYSTIMESTAMP: 28-12月-10 12.51.57.593000 下午 +08:00
SYSDATE: 2010-12-27 23:51
应用服务器
TZ_OFFSET('PRC'): +08:00
CURRENT_DATE: 2010-12-28 12:55
CURRENT_TIMESTAMP:28-12月-10 12.55.00.750000 下午 +08:00
LOCALTIMESTAMP: 28-12月-10 12.55.00.750000 下午
DBTIMEZONE: -07:00
SESSIONTIMEZONE: +08:00
SYSTIMESTAMP: 28-12月-10 12.55.00.750000 下午 +08:00
SYSDATE: 2010-12-27 23:55
发现从两个服务器上返回的结果差不多,sysdate的时间跟其他时间不一致,跟服务器时间也不一致。
理论上说sysdate应该是取服务器的时间。确认服务器操作系统的时间,时区也是+8:00,没问题。数据库的时区是-7:00,难道是数据库时区的问题?
在本地做实验,无论数据库的时区更改为任何时区,sysdate返回的时间都是正确的,除非数据库服务器的时区更改,这样数据库服务器操作系统的时间有变化,sysdate的时间也有变化。没有重现现场的sysdate与数据库服务器操作系统时间不一致的情况。
查看oracle sys.standard包中的sysdate函数发现函数代码如下:
-- Bug 1287775: back to calling ICD.
-- Special: if the ICD returns NULL, that means we should do the old
-- 'SELECT SYSDATE FROM DUAL;' thing. This allows us to do the SELECT from
-- PL/SQL rather than having to do it from C (within the ICD.)
function sysdate return date is
d date;
begin
d := pessdt;
if (d IS NULL) then
select sysdate into d from sys.dual;
end if;
return d;
end;
难道是因为系统取不到pessdt这个c语言的日期,所以使用老的 'SELECT SYSDATE FROM DUAL;' 取时间,转换了时区的关系?
于是要求现场修改数据库时区:
alter database set time_zone='+8:00'
重启数据库
修改过程中遇到问题:ora-02231,ora-30079,是因为数据库中存在字段使用 timestamp with local timezone的字段类型
使用下列语句查找到该字段:
select u.name || '.' || o.name || '.' || c.name
TSLTZcolumn from sys.obj$ o, sys.col$ c, sys.user$ u
where c.type# = 231 and o.obj# = c.obj# and u.user# = o.owner#;
删掉不需要的字段:
alter table oe.orders drop column order_date;
再修改时区成功。
问题解决。
但是还是不确定是不是因为系统取不到pessdt这个c语言的日期,所以使用老的 'SELECT SYSDATE FROM DUAL;' 取时间,转换了时区的关系。
请哪位高手帮忙分析一下?
[本帖最后由 whaphy 于 2010-12-28 16:09 编辑]