水曜日, 6月 18, 2008

DB2のJDBC Type2にハマる

今日、仕事場でよくわからない現象が発生した。 それは、次のような事象でした。 各端末で次の操作をおこなう。 Javaでmarge文を発行(PrepareStatement#executeUpdate()) 対象DBはWindows2000server DB2 v8.2で更新するのは同じDBインスタンスの同一レコード 他にそのレコードは更新しない状況下であることは当然 marge実行時の戻り値が変なんです。 JDBCのAPI仕様上、PrepareStatement#executeUpdate()はreturn intとなってます。
  1. 端末Aでは、mergeのreturn 1
  2. 端末Bでは、mergeのreturn 0
  3. 端末Cでは、mergeのreturn 1
というような結果になった。 ちなみに端末A,B,Cの全てで対象レコード1件が更新(when matched then)されます。 ここで、結果を見直すと・・・ 「何で端末Bではreturn 0なんだ??」って状態になるんです。。。 最初はクラスローダが読み込んでいるJDBCドライバのverが違うのかな?と思っていたんですが、そういうわけでもないみたい。 (みんな、同じくDB2 v8のレガシードライバだということはすぐにわかったんですが。。。) ここからは、わかったことを
  1. 端末Aは確かにbuildlevelっていう値がB,Cとは違っていたが、BとC同じだった。
  2. 端末Bで使用しているドライバをClassLoader#getResource()で導き出し、端末Aで使用してもreturn 0になるわけではない。(return 1)
  3. java.sql.Connection#getMetaData()#getDriverVersion()を見てみると、同じドライバクラスを利用しているのに表示されるバージョンが違うということに気づく
  4. とりあえず、DB2Driverクラスを逆コンパイルしてソースを追いかける。
  5. getDriverVersionをどんどん追跡していくと。。。
  6. nativeメソッドにたどり着き、そこでふと気づく「そういや、Type2で接続してたんだよね。。。」
  7. Type2ってのはType4のようにダイレクトに接続するのではなく、一端クライアントのネイティブライブラリを通して接続する種類であることを思い出し、DB2Driverクラスが読み込んでいるdllを探し始める
  8. 端末ごとにdllのversionをチェックしてみると驚きの結果が。。。
場所 :db2jdbc.dll :LegacyDriver(buildlevel) 端末A :8.1.7.447 :s040812(DB2Clientのdb2java.zip) 端末B :8.1.0.36 : s021023(Websphere付属?のdb2java.jar) 端末C :8.1.8.762 :s021023(Websphere付属?のdb2java.jar) みんな、バラバラやん!! そりゃないよ。。。 しかし、dllのversionが8.1.0だとmargeのreturnが0になるってどうなんだろ?? 最終的に端末Bのクライアントを再インストールしてとりあえず解決とした。 (FixPackを適用すれば回避できるかも。。。)

0 件のコメント:

failed to read qemu headerのときのメモ

かなり久々。。。 忘れないようにここに書きこんでおく。 ちょっとした手違いで libvirtでイメージを起動しようとすると failed to read qemu header なんておっしゃられて起動しない。。。 vmwareserverを使って...