【ojdbc14.jar】由於Oracle驅動ojdbc14.jar導致千萬富翁破產之始末

secooler發表於2012-03-09
  這是一個“千萬富翁”瞬間變為“貧民”的真實過程。且聽我慢慢道來。

1.故障模擬過程
  1)先看一段JAVA程式碼對字串讀取轉換後的數值表示形式的差異
  這段程式碼實現的功能是從平文字檔案中將字串表示形式的內容轉化為數值並列印出結果。
Normal 0 false false false EN-US ZH-CN X-NONEpackage org.seco.sclcore.test;   import java.math.BigDecimal;   public class Sample {     /**    * @param args    */   public static void main(String[] args)   {     // TODO Auto-generated method stub         System.out.println(getSalesMoney("26947280"));     System.out.println(getSalesMoney("122936367"));   }     public static BigDecimal getSalesMoney(String value)   {     String stringValue;     boolean isNegative = false;     if (value.indexOf("-") != -1)     {       stringValue = value.replace("-", "");       isNegative = true;     }     else     {       stringValue = value;     }     BigDecimal result = BigDecimal.ZERO;     if (isNegative)     {       double doubleValue = -1;       result =           BigDecimal.valueOf(Double.valueOf(stringValue).doubleValue()).multiply(               BigDecimal.valueOf(doubleValue));     }     else     {       result = BigDecimal.valueOf(Double.valueOf(stringValue).doubleValue());     }     return result;   }   }
2)程式碼輸出結果
  程式碼中顯式的將"26947280"和"122936367"字串讀取並轉化為數字。結果對應如下:
"26947280"  -- 2.694728E+7
"122936367" -- 122936367

  規律:字串中以數字零結尾的內容轉化為數字後以2.694728E+7這種科學計數法的形式儲存,而非零幾位的內容還是以原有形式顯式。

  重點關注科學計數法表示的結果,此處"26947280"結尾處的零已被去掉。2.694728E+7這種科學計數法表示的數字就是數字26947280,此處沒有問題。

  3)入庫後故障出現
  JAVA程式碼將結果儲存到Oracle資料庫後,詭異的事情發生了。原先以科學計數法顯示的2.694728E+7數值被存入Oracle資料庫後變成了26.9472,如下所示。

錯誤值    實際值
26.9472    26947280

  這種錯誤是絕對無法容忍的。
  原本將近兩千七百萬人民幣的資產幻滅了,變成了不到二十七元人民幣。這是何等的荒謬,誰都是無法承受這種從千萬富翁變為貧民的打擊。

2.故障分析過程
  看到這個荒謬的錯誤後我們需要做的是冷靜、冷靜……還是冷靜。
  仔細的去分析導致這個錯誤的最終原因到底在哪裡。
  1)第一種推測:JAVA本身的問題
  這種可能性基本可以排除。因為在我們的測試程式碼中返回的數值上看,即便數字表示形式不一樣(科學計數法與否),但是最終轉化為數值是忠於原字串本身內容的。也就是說
2.694728E+7就是表示26947280,122936367還是其自身。

  2)第二種推測:Oracle資料庫本身的問題
這種可能性也站不住腳,試想一下,作為一款大牌商業資料庫軟體的Oracle怎麼會隨隨便便將客戶的資料篡改呢。
Oracle會將應用程式傳過來的內容原原本本的存放到資料庫中,用於後續的展示或處理。

  3)第三種推測:問題出在應用程式和Oracle資料庫之間
  JAVA應用程式是透過ojdbc14.jar這個驅動程式與Oracle資料庫進行銜接的。莫非問題出在這個環節?
  (1)檢視當前ojdbc14.jar檔案的版本
  版本檢視方法:可以使用解壓軟體開啟ojdbc14.jar檔案,檢視META-INF資料夾中的MANIFEST.MF檔案,內容如下:
Manifest-Version: 1.0
Specification-Title:    Oracle JDBC driver classes for use with JDK14
Sealed: true
Created-By: 1.4.2_08 (Sun Microsystems Inc.)
Implementation-Title:   ojdbc14.jar
Specification-Vendor:   Oracle Corporation
Specification-Version:  Oracle JDBC Driver version - "10.2.0.1.0"
Implementation-Version: Oracle JDBC Driver version - "10.2.0.1.0"
Implementation-Vendor:  Oracle Corporation
Implementation-Time:    Wed Jun 22 11:19:45 2005

Name: oracle/sql/converter/
Sealed: false

Name: oracle/sql/
Sealed: false

Name: oracle/sql/converter_xcharset/
Sealed: false

  可見,這裡使用的是10.2.0.1.0這個10g版本中的最基礎的驅動程式。

  (2)嘗試下載10g最新的驅動程式重新測試
10g的最新ojdbc14.jar檔案的版本資訊如下:
Manifest-Version: 1.0
Specification-Title:    Oracle JDBC driver classes for use with JDK14
Sealed: true
Created-By: 1.4.2_14 (Sun Microsystems Inc.)
Implementation-Title:   ojdbc14.jar
Specification-Vendor:   Oracle Corporation
Specification-Version:  Oracle JDBC Driver version - "10.2.0.5.0"
Implementation-Version: Oracle JDBC Driver version - "10.2.0.5.0"
Implementation-Vendor:  Oracle Corporation
Implementation-Time:    Thu Apr  8 03:40:31 2010

Name: oracle/sql/converter/
Sealed: false

Name: oracle/sql/
Sealed: false

Name: oracle/sql/converter_xcharset/
Sealed: false

  10g最新版本的驅動是10.2.0.5.0。
  在更換了驅動程式之後,之前的故障迎刃而解。原來罪魁禍首就是APP與DB之間的驅動程式
ojdbc14.jar

3.故障處理方法
  透過上面的分析過程已經確認是Oracle驅動程式ojdbc14.jar版本過低導致的,因此故障處理方法很直接,替換生產環境中10.2.0.1版本的驅動為10.2.0.5驅動。

4.小結
  本文中提到的故障場景影響是很惡劣的。即便在替換驅動後依然有很多善後工作要做,比如將已經入庫的錯誤資料的查詢並調整正確。
  在JAVA應用程式和資料庫之間的驅動選取方面需要注意,基本要求,保證驅動版本和資料庫的版本保持一致,或者使用較新版本的驅動程式。
  這個故障帶給我們的啟示是:任何一個環節都有可能存在重大的隱患,細緻嚴謹永遠是IT人最重要的職業素質。

Good luck.

secooler
12.03.09

-- The End --


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/519536/viewspace-718209/,如需轉載,請註明出處,否則將追究法律責任。

相關文章