Windows Server 2003R2 + Oracle10g から Windows Server 2008R2 + Oracle11g 移行の備忘録

# はじめに
Windows Server 2003R2は、2015年7月15日にサポートが終了するということで、2014年4月から準備を始めてWindows Server 2003 + Oracle10g から Windows Server 2008R2 + Oracle11gに2014年8月から30近くある拠点に順次移行作業を行いました。
移行する際にいろいろ問題が発生したのですが、3年経って安定したことで備忘録として解決した方法などを書いていきます。
もはや、Windows Server 2003R2からの移行ネタは需要はないのですが、最新ネタをあえて出さないという戦略もあるということでご了承ください。

2014年なら、移行する選択としてWindows Server 2012R2 + Oracle12cもあったわけですが、ダウングレード権を行使して最新版は使わない選択をしています。これは Windows Server 2008R2 + Oracle11gを使用した方がノウハウの蓄積があり、何かトラブルが発生した場合でも解決がしやすいということと、最新機能を使う必要性に迫れられていないからです。トラブルを避けたい企業の戦略からすれば当然からも知れません。

# 変更点
Windows Server 2003R2 + Oracle10g から Windows Server 2008R2 + Oracle11gに移行する上で何が大きく変わったのか列挙します。

## Windows Server 2003R2 と Windows Server 2008R2の違い
* 32bitOSから64bitOSへ
* IIS6.0からIIS7.5へ
* セキュリティの強化
* セッション0の分離
* 電源プラン機能の追加
* タスクスケジューラから実行時のカレントディレクトリ
* 初期状態が短い日付形式(yy/mm/dd) から長い日付形式(yyyy/mm/dd)へ
 
## Oracle10g と Oracle11g の違い
* パスワードの大文字と小文字の区別が標準
* ユーザパスワード有効期限のデフォルト180日になった
* 証跡取得機能がデフォルトONになっている

パスワードは設定変更することで、Oracle10gと同様にすることが可能。

# 検証作業
「Windows Server 2003R2 と Windows Server 2008R2の違い」の項目から既存アプリケーションの25システムが正常動作するか検証する。
また、システム導入時のバッチなどの見直しも必要となる。

## 32bitOSから64bitOSへ
既存アプリケーションのほとんどがレガシーASP(Classic ASP)で動作していることから、基本32bitモードで動作させる。

その為、32bitモードで動作させる知識が必要となる。

アプリケーションが32bitか64bitのどちらかで動作しているかは タスクマネージャでは、 「プロセス」タブで表示されるプロセスに 32ビット動作のものは「*32」と表示される。

### Wow64
64bit版でもWindows-32-on-Windows-64(WOW64)といわれる仮想環境化で動作するため、ほとんどのアプリケーションは動作する。

フォルダ名がややこしいです、「32」と「64」の対応が逆です。
64bit用のソフトを動かすときは「System32」にあるファイルを使います。
32bit用のソフトを動かすときは「SysWOW64」にあるファイルを使います。

### Program Filesフォルダ
インストール先フォルダとしてProgram Filesフォルダが使われる。
「ユーザーが判りやすいように」分けているだけで、実際にはどちらにインストールしても問題は無い。※どちらも書き込み権限に注意は必要

|フォルダ|内容|
|:--|:--|
|Program Files| 基本的に、64bit ネイティブアプリケーションがあるフォルダ。|
|Program Files (x86)|基本的に、32bit アプリケーションがあるフォルダ|
参照:[32bitがx86、64bitがx64で表わされる理由](http://helpsupport.blog.fc2.com/blog-entry-103.html)

### デバイスドライバー
デバイスドライバー(ODBCやプリンタドライバー等)などハードウェアに近い部分は、各社の提供されている64bit版ドライバーを導入する必要がある。

既存アプリケーションがDelphi5製ということもあってBDE (Borland Database Engine)の導入が必要になったのですが、64bit上では通常はエラーになってインストールできませんでした。
その件についてインストール方法を2015年に下記ブログに書きました。
参照:[64bitOSへのBDEインストール](http://blogs.wankuma.com/yaju/archive/2015/12/24/524977.aspx)

### Oracle Client
Oracleを使用する32bit アプリケーションでは、Oracle Client 32bit版を使用する。よって、サーバー上にOracle Clientの32bitと64bitを混在した状態でインストールをしている。

### .NETアプリケーション
.NETアプリケーションがAnyCPUの場合は64bitモードで動作してしまうため、32bit版のドライバーを使うようになっていると、例外エラーが発生する。

* Oracle.DataAccess.dll 32bit版を用いたアプリケーション
* Microsoft.Jet.OLEDB.4.0を用いたアプリケーション  
※64bit版Windowsには「Microsoft.Jet.OLEDB.4.0」が提供されていない

x86でコンパイルすることで使用するDLLも32bitモードで動作する。
参照:[64bit版Windowsでの「Microsoft.Jet.OLEDB.4.0」について](http://qiita.com/yaju/items/86314412741deb806366)

### レジストリ登録やスクリプト実行など
レジストリやDCOM コンポーネントなどは、32bitと64bitで情報の格納先が分離されているため、登録する際などには32bit専用のものを使用する。
64bit版Windowsではデフォルトでは64bit版が動作するので、64bitバッチ内で32bit版を使う場合は「%systemroot%\SysWoW64」フォルダを指定して使用する。ものによっては「/32」スイッチをつけて起動する。
※コマンドプロンプトやスクリプト実行を32bit版で動かせば、処理内も32bit版で動作する。

|32bit|64bit|内容|
|:--|:--|:--|
|%systemroot%\SysWOW64\regedit.exe|regedit.exe|レジストリ編集画面|
|%systemroot%\SysWoW64\regsvr32.exe|regsvr32.exe|レジストリ登録・解除|
|%systemroot%\SysWOW64\cmd.exe|cmd.exe|コマンドプロンプト|
|%systemroot%\SysWOW64\wscript.exe|wscript.exe|スクリプト実行|
|%systemroot%\SysWOW64\cscript.exe|cscript.exe|スクリプト実行|
|mmc.exe comexp.msc /32|mmc.exe comexp.msc|コンポーネント サービス画面|
|dcomcnfg.exe /32|dcomcnfg.exe|コンポーネント サービス画面|
参照:[WscriptとCscriptの違い](http://wsh.style-mods.net/topic3.htm)

## IIS6.0からIIS7.5へ
IIS6からIIS7.5でIISの設定画面が大きく変わっているため、慣れるまで操作面で何がどこにあるのか分かりにくかった。

既存アプリケーションは、レガシーASP(Classic ASP)で動作させているため、マネージパイプラインモードというのをクラシックにする必要がある。

Classic ASPは既定では動作が無効になっているため、下記の設定を行う。
・サーバの役割でASPのサービスを有効にする
・IISには仮想ディレクトリではなく、アプリケーションで追加する
・アプリケーションプールは「統合」ではなく「クラシックを使う」
・アプリケーションプールの32ビットアプリケーションの有効化をTrueにする

### 参照
 * [IIS 7.0 および IIS 7.5 上で Classic ASP アプリケーションを実行する](https://technet.microsoft.com/ja-jp/library/ee155445.aspx?f=255&MSPPError=-2147217396)
 * [IIS5.0からIIS7.0もしくはIIS7.5への移行](http://blog.livedoor.jp/hentaiga/archives/51491846.html)
 * [Windows Server 2008/ 2008 R2/2012 Web/FTP サーバ 新規導入設定ガイド(pdf)](http://jp.fujitsu.com/platform/server/primergy/technical/construct/pdf/win2008-web-ftp-guide.pdf)
 * [Classic ASP スクリプトのエラー メッセージはもはや既定では Web ブラウザーに表示されない](http://technet.microsoft.com/ja-jp/library/ee175739.aspx)
 * [Classic ASP の詳細エラーをブラウザーで表示できるようにする](http://network.station.ez-net.jp/server/microsoft/iis/classicasp_error.asp)

## セキュリティの強化
ユーザーアカウント制御(UAC)機能が追加された。
参照:[管理者権限での実行を制限するユーザー・アカウント制御UAC（前編）](http://www.atmarkit.co.jp/fwin2k/vista_feature/07uac01/07uac01_01.html)

Windows ファイアウォールは既定値で有効、追加する役割やサービスの内容に応じて、必要なところにだけ「穴」を開けるように変わっている。
参照:[【第52回】Windowsファイアウォールの設定(前編)](https://news.mynavi.jp/itsearch/article/hardware/874)

Oracleをクライアントから接続する際にWindows ファイアウォールで 通信できるようにポートの解放をする必要がある。
参照:[Oracle Database 　Windows ファイアウォール設定](http://www.projectgroup.info/documents/Oracle/ORA-000001.html)

## セッション0の分離
Windows Server 2008以降では「セッション0の分離」と呼ばれる機能が搭載されました。

>Windows Server 2003以前では、システムプロセスやサービス・ログインユーザが起動するアプリケーションは、全てセッション0で起動されていましたが、Windows Server 2008以降では、システムプロセスやサービスと、ログインユーザが起動するアプリケーションを同じセッションIDとするのは、セキュリティ上危険という理由から、ログインユーザが起動するアプリケーションは全てセッション1以上が割り当てられるようになりました。
セッション 0 ではユーザインターフェース(Windows のポップアップ画面など）を表示させることは出来ません。よって、サービスプログラムがユーザにポップアップ画面を表示が出来なくなりました。

Windows Server 2003R2時にはDCOMを使ってWindows サービスプログラムと同じプログラムを実行させるとプロセスは同じなのでOracleコネクションを使いまわすことが出来たのですが、セッション0の分離によりプロセスが別途起動するようになってしまいました。
このため、Windows Server 2008R2ではWindows サービス化をやめてDCOMを使ってプログラムを実行するだけにしました。あと、 DCOM 構成で ID タブ内の「対話ユーザ」では起動できなくなったため、「このユーザー」に変更しました。

## 電源プラン機能の追加
Windows Server 2008R2ではバランス、省電力、高パフォーマンスの 3 つの電源プランが組み込まれており、初期値はバランスになっています。

Webアプリケーションの応答が遅くても2秒未満の運用が求められているところで、2～4秒が多発するという問題が発生しました。データベースまわりなどいろいろ調べても解決できなかったが、電源プランの存在に気がつき設定を「高パフォーマンス」に変更することで解決しました。(設定変更は再起動することなく反映されます)

パフォーマンスが必要なサーバーであれば、電源プランは気にしておきましょう。

## タスクスケジューラから実行時のカレントディレクトリ
手動でバッチファイルを実行するとログが出力されるが、タスクスケジューラーからだとログが出力されないならまだいい方で動作しないってことも起きます。

これはタスクスケジューラを実行した際に、カレントディレクトリを指定しないとシステムフォルダ(%systemroot%\system32 または %systemroot%\SysWOW64)が指定されるため。

タスクスケジューラーでプログラム指定時にある「開始(オプション)(T)」に、作業フォルダーを指定することで、作業フォルダーがカレントディレクトリとなる。
または、実行プログラム(バッチ)内でカレントディレクトリを指定「cd /d %~dp0」する。

###  バッチファイルが画面に表示されない
「[Windows7でタスクスケジューラから実行するバッチファイルが画面に表示されません。](https://answers.microsoft.com/ja-jp/windows/forum/windows_7-winapps/windows7%E3%81%A7%E3%82%BF%E3%82%B9%E3%82%AF/ccff2c2f-5a0e-4f3d-ae81-9dff3e36fc3c?auth=1)」に下記の回答がありました。
>「ログオンしているかどうかにかかわらず実行する」になっていれば、必ずバックグラウンドで実行されるのでコマンドプロンプトの姿を見ることはできません。
画面に表示させたいなら、「ログオンしているときのみ実行する」にする必要がありますが、その文面通り、ログオンしていないときは実行されなくなるので、メリット/デメリットを考慮して検討してください。


## 初期状態が短い日付形式(yy/mm/dd) から長い日付形式(yyyy/mm/dd)へ
Windows Server 2003R2で使用していたバッチをWindows Server 2008R2で実行したところ、日付が変な状態で出力された。
原因は、Windows Server 2003R2では、コントロールパネル→地域のオプション→日付タブが短い形式(yy/mm/dd)になっていたが、Windows Server 2008R2では長い形式(yyyy/mm/dd)となっていたため。

```bat:日付パース変更
%date:~-8,2%%date:~-5,2% -> %date:~-10,4%%date:~-5,2%　　
```

# トラブル
移行にともない調査した上で変更点を適切に設定し、既存アプリケーションも正常に動作することを確認したにもかかわらず、実運用になってトラブルは発生するわけです。残念ながら調査に漏れた部分もありますし、この設定がこんなにところに影響するのかってもあります。

## 実行アプリケーションが遅い
【現象】
電源プランの「高パフォーマンス」に変更によって、実行アプリケーションの応答は改善されたのですが、ログを調査するとまだ平均500msの中で1秒以上がそれなりに発生していることが分かりました。

【原因】
複数のサーバー内でも、この現象が発生するサーバーと発生しないサーバーがありました。プロセスとサービス状態の一覧を出力して比較したところ、「OracleDBConsoleサービス」に状態に違いが見られました。現象が発生しないサーバーは停止されていたのです。そもそも停止する設定にはしていなかったはずなのですが、たまたまエラーになって停止していたのです。

「OracleDBConsoleサービス」はOEM(Oracle Enterprise Manager)に関するサービスでWebベースのオラクルの統合管理ツールで使用します。

【対応】
旧サーバーでは「OracleDBConsoleサービス」は起動させておいても速度には影響は出ていなかったのですが、Oracle11gになって情報収集量が増加したせいか影響が出るようになってしまったようです。
OEM(Oracle Enterprise Manager)については、調査する際だけ使用させればいいとして、「OracleDBConsoleサービス」は停止しました。
これにより、1秒以上発生することがほぼ無くなりました。

## セッション切れ
【現象】
Webアプリケーションではセッションを使用しており、セッションが切れた場合にはログイン画面に戻すようになっているのですが、タイミングが悪い場合にはデータ不整合になってしまうのです。
複数サーバーのどこかで1ヶ月内に数回は時間帯不定期で発生していました。発生するサーバーでも数ヶ月発生しないこともあるのです。

【原因】
Oracleの認証方式にOS認証があります。新サーバーでは認証方式はデフォルト設定のOS認証有りにしており、旧サーバーではOS認証無しでした。
Oracleサポートに問い合わせして得られた対処方法が、sqlnet.oraファイルにあるOS認証有り(NTS)をOS認証無し (NONE)に変更してはどうかという提案でした。

認証方式とセッション切れとは関係ないと思われたのですが、設定をOS認証無しに直してから半年ほど経っても一度も発生しなくなっていることから、ほぼ確定と思われます。

【対応】
sqlnet.oraファイル
[変更前]-OS認証有り
SQLNET.AUTHENTICATION_SERVICES= (NTS)
[変更後]-OS認証無し
SQLNET.AUTHENTICATION_SERVICES= (NONE)

## SQLの実行結果に30分以上かかる
【現象】
ある既存アプリケーションを動作させたところ、実行結果が返ってくるまでに30分以上かかるようになってしまった。

内部でサブクエリを使ってグループ化した後に、同じテーブルで結合しているSQLがあり、実行計画を見るとGROUP BYのところがHASHが使われず、FULLのままになっている。

【原因】
Oracle11gの実行計画だと遅い、Oracle10gにする統計情報は同じにも関わらず実行計画が変わってしまい、処理が遅くなってしまう。
参照:[Oracle Database 10gから 11gへのアップグレード：オプティマイザ機能の詳細(pdf)](http://www.oracle.com/technetwork/jp/database/focus-areas/bi-datawarehousing/twp-upgrading-10g-to-11g-what-to-ex-133707-ja.pdf)

【対応】
Oracle10gと同じようにするヒント句をSQLに追加した。

```sql
SELECT
  /*+ OPTIMIZER_FEATURES_ENABLE('10.2.0.1') */ 
```

* [Oracle Database パフォーマンス改善 『オプティマイザ指定』](http://www.casleyconsulting.co.jp/blog-engineer/oracle/oracle-database-%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9%E6%94%B9%E5%96%84-%E3%80%8E%E3%82%AA%E3%83%97%E3%83%86%E3%82%A3%E3%83%9E%E3%82%A4%E3%82%B6%E6%8C%87%E5%AE%9A%E3%80%8F/)

* [Oracle10gから11gへ移行した後でも実行計画を10gと同じにする方法](http://www.lesstep.jp/wiki/index.php?Oracle10g%E3%81%8B%E3%82%8911g%E3%81%B8%E7%A7%BB%E8%A1%8C%E3%81%97%E3%81%9F%E5%BE%8C%E3%81%A7%E3%82%82%E5%AE%9F%E8%A1%8C%E8%A8%88%E7%94%BB%E3%82%9210g%E3%81%A8%E5%90%8C%E3%81%98%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)
* [SPMの使用方法：アプリに手を入れずに実行計画を変更する方法](http://odakeiji.blog33.fc2.com/blog-entry-164.html)
* [【Oracle】 カーディナリティ・フィードバック(Cardinality Feedback)](http://fujikkoooooo.hateblo.jp/entry/2015/04/27/133450)

# 最後に
サーバー移行によりサーバーPC自体もCPUやメモリ等が良くなっているのだから、Windows Server 2008R2 + Oracle11g になっても性能が上がるか最悪は同等だろうと思っていました。
実際に性能テストでは旧サーバーと同等程度という結果で、電源プランがバランスでも問題なかったのですが、実運用では実行アプリケーションを長時間動かすため、電源プランのバランスによって影響が出てしまったのです。
サーバーの性能が全体的に上がったので悪くはならないだろうという甘い判断とコスト面もあり簡易的な性能テストに留まってしまったのです。

セキュリティやエコという名目で性能が削られてしまうんですよね。これに加えてウィルス対策ソフトが加わるわけですから、性能検証は気を付けましょう。