eygle.com   eygle.com
eygle.com  
 

« 结束IT168《循序渐进Oracle》技术交流会 | Blog首页 | 《循序渐进Oracle》在当当网上 »

497天是一个轮回-记Linux时钟的回转

作者:eygle |【转载时请以超链接形式标明文章和作者信息及本声明
链接:
前几天,同事告诉我一个发现,他说一台数据库的运行时间超过了操作系统的启动时间。
从数据库内部可以查询到数据库实例的启动时间:
SQL> COLUMN STARTED_AT format A25
SQL> COLUMN UPTIME format A50
SQL> SELECT TO_CHAR (startup_time, 'DD-MON-YYYY HH24:MI:SS') started_at,
  2            TRUNC (SYSDATE - (startup_time))
  3        || ' day(s), ' || TRUNC (  24 * ((SYSDATE - startup_time) -
  4        TRUNC (SYSDATE - startup_time)))
  5        || ' hour(s), '|| MOD (TRUNC (  1440 * (  (SYSDATE - startup_time) -
  6        TRUNC (SYSDATE - startup_time))),60)
  7        || ' minute(s), '|| MOD (TRUNC (  86400 * (  (SYSDATE - startup_time) -
  8        TRUNC (SYSDATE - startup_time))),60)
  9        || ' seconds' uptime
10  FROM v$instance;

STARTED_AT                UPTIME
------------------------- --------------------------------------------------
05-JUL-2005 10:36:58      803 day(s), 2 hour(s), 27 minute(s), 55 seconds

从这里看数据库实例启动了803天左右,也就是说自2005-07-05开始这个数据库一直在不间断的运行着。

而从操作系统的uptime来看,系统不过启动了306天:
SQL> ! uptime
13:06:21  up 306 days, 19:00,  1 user,  load average: 0.00, 0.00, 0.00

同事问我原因,首先我们检查alert文件,发现数据库的确是2005年启动的。
如果日志记录的是没有问题的,我当时猜测是否可能是由于系统时钟的更改,使得uptime的显示出现问题。

但是始终觉得这个解释并不充分,今天再研究一下,发现了问题本质。
和以前研究过的问题完全类似,这是又一次时间溢出的问题,
http://www.eygle.com/archives/2004/11/job_can_not_execute_auto.html
http://www.eygle.com/archives/2006/06/time_stop_again.html

由于某些Linux内核使用32位无符号长整型来计算时间,32位的最大值就是0xffffffff,再加1就将溢出变为0
以下一小段C代码可以解释这种溢出:
[root@jumper root]# cat a.c
int main(void){
unsigned int num = 0xffffffff;

printf("num is %d bits long\n", sizeof(num) * 8);
printf("num = 0x%x\n", num);
printf("num + 1 = 0x%x\n", num + 1);

return 0;
}
[root@jumper root]# gcc -o un a.c
[root@jumper root]# ./un
num is 32 bits long
num = 0xffffffff
num + 1 = 0x0

在我的这个Linux发行版本上,这个时间就此溢出:
SQL> ! uname -a
Linux moto 2.4.21-15.ELsmp #1 SMP Thu Apr 22 00:18:24 EDT 2004 i686 i686 i386 GNU/Linux

SQL> ! cat /etc/redhat-release
Red Hat Enterprise Linux AS release 3 (Taroon Update 2)

我们根据497天再来计算一下:
SQL> select 803 - 306 from dual;

  803-306
----------
      497
当前数据库的显示是正确的,803天减去uptime显示时间,得出的正好是497天。

这才是这次异常的本质所在。     
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.6.0 - Production
PL/SQL Release 9.2.0.6.0 - Production
CORE    9.2.0.6.0      Production
TNS for Linux: Version 9.2.0.6.0 - Production
NLSRTL Version 9.2.0.6.0 - Production

-The End-

历史上的今天...
      >> 2008-09-16文章:
      >> 2005-09-16文章:
             Tom's New book has landed
      >> 2004-09-16文章:
------
这篇 【497天是一个轮回-记Linux时钟的回转】来自 www.eygle.com | CSDN技术网摘| del.icio.us|365Key

By eygle on 2007-09-17 12:59 | Comments (6) | Posted to Case | Internal | Edit |Pageviews:

相关文章 随机文章
  • Oracle10gR2中的Mutex竞争的案例
  • CURSOR_SPACE_FOR_TIME 参数废弃
  • 关于Mutex的笔记
  • DBA警示录:Messages信息应当认真检查
  • 歌华经历的数据库"攻击"
  • 曲终人散意尤存 - OOW 2008 结束
    My answer for-9个动态性能视图
    香山赏红叶 北京秋意浓
    苏州游记
    如何从自动备份中恢复控制文件和SPFILE文件
    搜索本站:

    留言 (6)

    Eygle研究可真深

    Posted by: edeed at September 17, 2007 10:46 AM

    是不是忒复杂

    Posted by: 鬼故事 at September 18, 2007 9:08 PM

    这个linux还真稳定。

    Posted by: dong at September 30, 2007 10:08 AM

    V$TIMERThis view lists the elapsed time in hundredths of seconds. Time is measured since the beginning of the epoch, which is operating system specific, and wraps around to 0 again whenever the value overflows four bytes (roughly 497 days).

    Posted by: warehouse at March 11, 2008 11:56 AM

    to warehouse:
    这个案例和v$timer没关系,v$timer的Bug在9.2.0.4之后就解决了。

    这个是Linux的问题,后期的版本也已经修正了这个Bug。

    Posted by: eygle at March 11, 2008 3:09 PM

    这个linux还真是不错哦`

    Posted by: 鬼故事 at August 21, 2008 3:54 AM

    发表留言:



    Remember Me?
    (输入验证码后方可评论,谢谢支持)



    CopyRight © 2004 eygle.com, All rights reserved.