首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle Job 停止執行診斷實錄:Solaris gethrtime() 497 天計時器溢位 Bug

     編輯:Oracle 資料庫基礎

事故現場

  • 平台:SunOS 5.8 (Solaris 8),Oracle 9.2.0.3。
  • 現象:所有 DBMS_JOB 排程任務於 2004-11-17 上午 01:00 後全部停止執行,DBA_JOBS.NEXT_DATE 顯示應執行時間已過,但 LAST_DATE 停留在前一天。手動 DBMS_JOB.RUN() 正常。

排查過程

  1. 懷疑 CJQ0 進程異常:嘗試 ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0 再設回 5,PMON 重啟 CJQ0,但 Job 仍不跑。反覆切換導致 CJQ0 直接死亡。
  2. 重啟資料庫:晚間重啟,CJQ0 正常啟動,但 Job 依然不執行。
  3. Metalink 搜尋關鍵字:slgcsf() / slgcs() on Solaris will stop incrementing after 497 days。命中 Bug 2658749 / 3018952。

根因分析

Solaris gethrtime() 返回奈秒數。Oracle 內部 slgcs() 封裝此呼叫作為高精度計時器。當系統運行時間超過 **497 天 2 小時 28 分鐘** (約 42949672950000000 奈秒),gethrtime() 返回值超過 32 位無符號整數上限,導致 slgcs() 固定返回 0xFFFFFFFF。

Job 排程邏輯 kkJSsrh() 依賴 slgcs() 計算下次執行時間差 (now - kkjlsrt)。計時器停止遞增 → 時間差恆為 0 → 排程判斷「尚未到期」 → 永不觸發執行。

驗證

bash-2.03$ uptime
10:00pm up 500 day(s), 14:57, 1 user, load average: 1.31, 1.09, 1.08
bash-2.03$ date
Fri Nov 19 22:00:14 CST 2004

主機運行 500 天,精確落在 497 天臨界點之後。

解決與後續

  • 臨時方案:安排重啟作業系統 (重置計時器)。重啟後 Job 恢復正常,V$TIMER 重新遞增。
  • 根治:Oracle 宣稱 9.2.0.6 Patchset 修復 (修改 slgcs() 處理溢位),但 Solaris 平台 9.2.0.6 當時尚未釋出。
  • 升級建議**:升級至 9.2.0.8 或 10g/11g,或遷移至 DBMS_SCHEDULER (10g+ 更穩健)。

經驗總結

  1. 遇到「不可能」的行為 (所有 Job 同步停擺、重啟無效),大膽懷疑平台/核心 Bug。
  2. V$TIMER (百秒計時器) 可作為快速健康檢查:若查詢兩次值不變,計時器已凍結。
  3. 長期運行的 Solaris 伺服器 (超過 497 天) 必須排程重啟或打補丁,否則 Oracle 內部計時依賴組件 (Job、Advanced Queuing、部分鎖超時邏輯) 將失效。
  4. 保持 Metalink 關注,建立關鍵字訂閱機制。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved