VIVA! Servers

MTSとRDBMSのいい関係

初音 玲 HATSUNE, Akira



 MTSとは何か?


 "MTSとは何か?"という問いは、"トランザクションとは何か?"という問いに行き着くだろう。トランザクションというのは、ある業務を行なうためのまとまった単位だ。たとえば、銀行に貯金を下ろしにゆくとしよう。


がひとつのトランザクションだ。そして、この手順のどこかで不都合(残高不足または記入ミス)が発見されたときには、用紙の記入からやり直しになる。そのため、口座からは引き出されるけれども現金が手元に来ないなどということが起きない様になっている。
 通常、RDBMSを使えば、このようなトランザクション処理は可能だ。しかし、ビジネスロジックをクライアント側から分離してRDBMSに実装しようとすると、ストアドプロシージャの開発言語として、Visual Basic以外の言語を習得しなければならない。また、ビジネスロジックで、メールなどを使う時にも、かなり面倒なことになる。
 そこで登場するのが、ビジネスロジックを配置するサーバーを別途設けた3階層C/Sシステムという考え方だ(図1)。そして、このビジネスロジック層で、トランザクションの管理を一括して行なう目的で開発されたのが、MTS(開発コード:Viper)だ(図2)。なお、MTSに登録されたActiveX DLLをMTSオブジェクト、そのMTSオブジェクトを使うクライアントをベースクライアントと呼ぶ。
 MTSを使うことにより、トランザクション管理以外にも、


というオブジェクトのプール機能が手に入り、限られたサーバー資源を有効に使うことができる。トランザクション処理以外のこれらの機能は、いわゆるORB(Object Request Broker)と呼ばれる類のソフトウェアが提供する機能とオーバーラップしている。もちろん、MTSをORBと呼ぶことを疑問視する向きもあるが、本格的なORBを導入するにしてもMTSで済ませるにしても、自家製のオブジェクト管理プログラムが必要ないということには変わりがない。MTSというと、その名称からトランザクション関係に目が行ってしまうが、MTSを使う本当の意味は、このオブジェクト管理関係の機能にあるのだ。


 Win95にMTSを入れる意義は?


 MTS 2.0からは、Windows NT 4.0だけではなく、Windows 95にもインストールすることができる。これは、MTSのクライアントモジュールをインストールできるという意味ではない。MTS自身をインストールできるという意味だ。このことは、"Windows 95をサーバー化する"という無謀なことをまたやっていると思われるかもしれないが(私もそう思った)、そのような目的でインストールできるようになったのではない。
 95でMTSを使う目的は、クライアントプログラムの動作環境としてMTSを使い、トランザクション対応のシステムを簡単に構築できるようにすることを目指している。そのため、Windows 95上でMTSを使うときには、


というような制限がある。


 また、MTSを使ったプログラムの開発プラットフォーム、またはMTSの管理クライアントとしてWindows 95を活用できるが、開発環境と実行環境を同一環境にするのは、システム開発の言わば鉄則のようなものであり、NT4.0上のMTSで稼動するプログラムをWindows 95/98上のMTSを使って開発およびテストすることは無意味であることを付け加えておく。
 なお今回は、スタンドアロンMTSアプリケーションの作成を通して、MTSプログラミングの手法を探ってゆきたいと思う。

 MTSの最初の使用例


 MTSをインストールしたマシン上に開発環境を構築したときには、MTSアドイン機能を使うことができる。このアドイン機能は、Visual BasicプロジェクトでMTS配下のActiveX DLLを、互換性のあるサーバーとして指定し、このプロジェクトからMTSへの反映を手軽に行なえるようにするための機能だ。この機能を使うためには、ActiveX DLLをMTS配下にするため、いったんMTSに該当ActiveX DLLを登録しておく必要がある。

 ActiveX DLLの作成

 MTSオブジェクトは、DCOMを使ってベースオブジェクトと連携する。普通、このようなときは、ActiveX EXEを利用することになる。しかし、ベースオブジェクトと直接連携するのはMTS自身だ。MTSとMTSオブジェクトは、同一空間で動作することで高パフォーマンスを目指している。そのため、DCOMを使うとはいえ、ActiveX DLLの形式でMTSオブジェクトを作成することになる。

 Object Controlインターフェイスの実装

 ActiveX DLLが作成できたら、MTSのオブジェクトプール機能を使うためのObject Controlインターフェイスを実装する。


ObjectControlを実装すると、


がクラスのメソッドに追加される。


 ObjectControl_CanBePoolメソッド

 MTSがオブジェクトをプールして良いかを判定するための値を返す(リスト2中の*1)。もし、Trueを返して、オブジェクトのプールを許すときは、ObjectControl_Deactivateメソッド内で変数の初期化などが必要だ。

 ObjectControl_Activateメソッド

 このメソッドは、ベースオブジェクトからMTSオブジェクトを使うときに、最初に呼び出されるメソッドだ。通常は、自コンテクストオブジェクトを変数に保存するような初期処理を記述する(リスト2中の*2)。

 ObjectControl_Deactivateメソッド

 ベースオブジェクトからMTSオブジェクトの使用が完了したときに、このメソッドが呼び出される。通常は、ObjectControl_Activateメソッドが呼び出されたときの状態へ復帰するための、変数初期化処理などを記述する。たとえば、コンテクストオブジェクトへの参照を解放するなどといった処理だ(リスト2中の*3)。

 MTSで実行する


 MTSオブジェクトは、MTSに登録するまでは、単なるActiveX DLLと同じだ。MTSに登録して初めて、MTSオブジェクトとして振る舞うことができる。通常、ActiveX DLLをMTSサーバーマシンにコピーする必要があるが、今回は、スタンドアロンMTSアプリケーションなので、Visual BasicでActiveX DLLにコンパイルしたら、すぐにMTSエクスプローラを起動して登録できる。


 MTSオブジェクトの登録時に、発生する間違いとしては、「コンポーネントウィザード」で[既存のオブジェクトをインポートする]を選択してしまい、インターフェイスが表示されない形で登録してしまうことだ。これは一見正常に登録できたように見えるが、「トランザクションの統計」などに情報が表示されない。もし、コンポーネントをどのように設定したか不明なときは、きちんとインターフェイスが表示されているか確認するのが良いだろう(リスト1)。
 このサンプルを動作させるときに、Windows 95のMTSを使うならば、ここで忘れてはいけないのは、MTSエクスプローラを立ち上げておくことだ。そうしないと、普通のActiveX DLLとしてMTSオブジェクトを使ってしまう。試しに、MTSエクスプローラを立ち上げている時といない時の、ベースクライアントの起動速度を比較してみてほしい。MTS起動直後では、明らかにMTSを立ち上げていた方が遅いはずだ。これは、ActiveX DLLの初期ローディングに関しては、MTSを経由した方が当然時間がかかるからである。


 コンテクストとは?


 MTSでトランザクションを扱うときは、コンテクストの理解が必要だ。MTSがActiveX DLLを使うとき、これと同時にコンテクストオブジェクトが自動的に生成される。このコンテクストオブジェクトこそ、MTSのセキュリティおよびトランザクションを管理するオブジェクトなのだ。よって、ActiveX DLLからさらに他のActiveX DLLを呼び出すときは、コンテクストオブジェクトを引き継いで、MTSの一括管理下に置けるようにする。そのための機能が、CreateInstanceメソッドだ。

 CreateInstanceメソッド

 コンテクストオブジェクトの正式名称は、ObjectContextオブジェクトだ。このオブジェクトのCreateInstanceメソッドを使うと、呼び出し元のActiveX DLLのコンテクスト情報を引き継いでオブジェクトを生成する。つまり、CreateObjectメソッドの代わりにCreateInstanceメソッドを使えばよい。

 ステートレスとステートフル


 きれいに設計されたメソッドは、どのような順番で呼び出しても、それぞれの機能を実行してくれる。つまり、メソッドの呼び出し順を気にしなくてもよい。このような状態をステートレスといい、MTSオブジェクトの理想的な姿と言える。たとえば、RDBMSに対する操作ならば、あるメソッドを呼び出せば、RDBMSの接続、検索、更新、切断まですべてを行なうようなものだ。
 しかし、一般的には、もう少し低機能のメソッドを用意して、何回かメソッドを呼び出して、ビジネスロジックを完成させることが多いだろう。このような時に"常に同じオブジェクトの別メソッドを呼び出すことができるか?"ということが問題になってくる。これはMTSオブジェクトの管理はMTSに一任しているために、あらかじめ何か指定をしておかなければ、オブジェクトが破棄されてしまったり他の利用者から使われてしまって、仕方なく別オブジェクトを生成し、そのメソッドを呼び出すようなことになるかもしれないということだ。
 そこで、MTSオブジェクトに状態を持たせて、その状態を保持している間は、いつも同じオブジェクトを利用者が利用できるようにする機能がMTSには存在する。このように状態を持った姿をステートレスに対して、ステートフルと呼ぶ。

 トランザクション管理


 MTSは、ステートフルを実現することは、トランザクションを管理することと等価だと考えている製品だ。よって、DAOまたはRDOのBeginTrans、CommitTranおよびRollBackメソッドに相当するMTSのメソッドを呼び出し、複数メソッドに渡るトランザクションを設定することでステートフルなMTSオブジェクトを作成する。

 DisableCommitメソッド

 MTSオブジェクトがステートフルであることを宣言し、さらに、SetComplateメソッドまたはSetAbortメソッドを実行するまでは、実際の更新を行なわないことも宣言する。

 SetComplateメソッド

 SetComplateメソッドは、MTSオブジェクトのすべての処理が正常に終了したことをMTSに通知するメソッドだ。このメソッドを発行すると、それまでの作業をすべて確定していく。なお、このメソッドを発行したあとに同じMTSオブジェクトを使おうと思っても、MTSは同じクラスの別オブジェクトを割り当てるかもしれない。

 SetAbortメソッド

 SetAbortメソッドは、MTSオブジェクトの作業を無効にしたいときに発行する。つまり、トランザクションのロールバックを行なう。このメソッドを発行したあとも、SetComplateメソッドと同様に、同じMTSオブジェクトを使おうと思っても、MTSは同じクラスの別オブジェクトを割り当てるかもしれない。

 トランザクションの設定

 MTSオブジェクトがトランザクションをサポートできるようにプログラムされていれば、MTSにもそのことがわかるようにしなければならない。それが、トランザクションの設定だ。MTSエクスプローラの[コンポーネント]から、該当オブジェクトの[プロパティ]を選択して[トランザクション]タブの内容を設定する(図4、表2)。通常、呼び出されるごとに別々のトランザクションとする、つまり、利用者ごとに別々に情報を管理することが大半であり、そのようなときは、[新しいトランザクションが必要]を選択する。
 なお、図4は、Windows 95のMTSエクスプローラだが、NT上では、[セキュリティ]タブが追加表示され、MTSロールの設定も可能になる。


 MTS使用例

 〜ODBC

 MTSは、MTSオブジェクトとODBCの間に入って、Microsoft DTC(Distributed Transaction Coordinator:分散トランザクションコーディネータ)を使って、トランザクションを提供する(図5)。
 このMicrosoft DTCは、元々はSQL Serverの一部としてリリースされたサービスであり、複数のSQL Server間の分散処理などを行なう目的で作られたマイクロソフト社の独自技術だ。
 MS DTCと連携してMTSよりODBCを使うためには、ODBC3.0以降のバージョンが必要だ。ここで難しいのは、ODBC3.0というのは、ODBCドライバのバージョンではなく、ODBCのレベル(仕様)のバージョンであるということだ。よって、ODBCドライバのバージョンを見ただけでは、それがODBC3.0以降のODBCドライバか不明なことが多い。
 このようにODBCドライバがどのレベルの仕様を満たしているかが重要なポイントではあるが、それ以外は、とくに注意を払わなくても普通にRDOまたはODBC Directを使って、MTSオブジェクトとしてプログラムすればよい。そして、RDOなどのトランザクション系メソッドの代わりに、MTSの3つのトランザクション系メソッドを使えば良いのだ。

 MTS使用例

 〜XAインターフェイス

 Microsoft DTCは、実質的にSQL Server専用のものだ。このことは、MTSのトランザクション管理の対象RDBMSがSQL Serverしか存在しないということを意味していた。しかし、MTSは、2.0になってから、XAインターフェイスプロトコルをサポートしている。XAインターフェイスプロトコルとは、X/Open DTP(Distributed Transaction Processing)仕様で規定されたトランザクション用の双方向システムレベルインターフェイスだ。Oracle、Sybase、IBM DB2、Informixなどの代表的RDBMS製品はこの仕様に準拠しているので、Microsoft DTCをサポートしていなくても、ODBCを使って、MTSからトランザクション管理を行なうことができる。

 適用できるOracleのバージョンは?

 XAインターフェイスがMTSの新バージョンからサポートされたということは、それに絡んでくるソフトウェアコンポーネント(ODBCドライバなど)もある程度新しいものが必要だということだ。これは、マイクロソフト社の製品を使う上での鉄則だ。Oracleに接続するためのソフトウェアコンポーネントとそのバージョンを表3にまとめた。
 ここで気が付くのは、相変わらずOracle 7までの対応であり、Oracle 8に対応していない点だ。Visual Basic 6.0付属のOLE DBプロバイダなども、同じようにOracle 7のみがターゲットだった。マイクロソフト社がOracle 8クライアントを作る能力がないとは思えないので、これは営業戦略的にOracle 8をターゲットから外しているように思える。これでは、"Oracle 8までサポートして高機能な他社製品を選択させるようなことはしたくない"のだと思われてもしかたがない。裏を返せば、SQL Server 7が機能的に見ればOracle 7.R7.3と同等だからということも影響しているようにも思える。


 適用するには?



 適用できたかを確認するには?

 MTS2.0をインストールすると、TestOracleXaConfig.exeというDOSベースのテストプログラムも同時にインストールされる。このテストプログラムを実行することで、XAインターフェイスを介した構成をチェックすることができる


 このテストさえ通過すれば、MS DTCを使ってSQL Serverと接続しているときのように、ODBCを経由してOracle 7と接続することが「仕様的には」できる。
 確かにXAインターフェイスを使えば、ODBCを経由してMTSとOracle間でトランザクションが連携可能だ。しかし、ここには大きな問題が含まれている。"ODBC経由のOracle接続が実用に耐えられるか"という点である。
 Visual Basic Magazineの特集でも、過去に何度かOracle用ODBCドライバの、バージョン間の相性問題などが取り上げられていたが、MTSだから、XAインターフェイスだからといって、その相性問題から逃れられる訳ではない。つまり、安定したODBCレベル3以上のOracle用ODBCドライバの入手が必要不可欠なのだ。そのためには、マイクロソフト社またはオラクル社が製品に添付してくるような中途半端なODBCドライバ(マイクロソフト社にしてもOracleと接続できなかったらSQL Serverを薦めればいいのだし、オラクル社にしてもODBCドライバではなく自社製のミドルウェアが存在する)ではなく、ODBCドライバそのものを売り物にしているような会社の製品を選択すべきだろう。

 MTS使用例

 〜Oracle Objects for OLE

 まともなODBCドライバをそれなりの料金を払って別途購入する解決方法もあるが、ここでは他の方法も探ってみよう。
 Visual BasicからOracleに接続する方法としては、Oracle Objects for OLEが選択されるようになってきた。Oracle Objects for OLEは、ActiveX DLLであり、CreateObjectを使ってオブジェクトを生成する。MTSオブジェクトからOracle Objects for OLEを使ってトランザクション管理ができるか確認してみる価値はある(リスト2)。
 さて、サンプルを動作させた結果だが、結論から言えば、


としたときで、まったく同じように動作してしまう。つまり、Oracle Objects for OLEは、MTSのコンテクストオブジェクトを介して管理できないということになる。
 こうなってくると、普通にOracle Objects for OLEを使うActiveX DLLを作成し、そのオブジェクト自体をプールさせたり管理したりする手段としてMTSを利用することになる。非常に残念だ。

 今後の課題と展望


 MTSの機能を調べてみると、オブジェクト管理(ORB)面での機能はある程度充実してきたが、トランザクション面での機能は、思ったほど強力ではないことが見えてきた。たとえばMTSで、実質トランザクション管理ができるのは、ODBC経由のRDBMS上のデータ操作だけなのだ。もちろん、XAインターフェイスという方向もあるが、Windowsの世界に対するトランザクション管理能力が決定的に不足している。Windows APIを使った処理までトランザクション処理の対象にする必要はないが、COMを介して連携しているようなオブジェクトに対する操作は、すべてトランザクションの対象として欲しいと思う。
 また、日本語版NTに対して、SP4をあてて、MTS 2.0を利用しているときには解決済みだが、英語版NTを利用しているときには、既知の障害が存在する。解決方法は、SP5を待つか、QFEをマイクロソフト社(http://www.microsoft.com/japan/products/ntupdate/nt4sp3/j041091.htm)から入手するかいずれかだ。

 NT Explorerのアクセス違反

 MTSを実行中に、Windows NT Explorerなどにアクセス違反が発生することがある。マイクロソフト社によれば、これは、サーバープロセスをシャットダウン中に初期化されていないhWndスタック変数により、不正なWindowsメッセージを動作中のアプリケーションに送るためだそうだ。

 セキュリティホールの可能性

 これも日本語版SP4では解決済みの問題だが、ActiveX EXEを代理サーバーにロードしてActiveX DLLに見せかけ、MTSに登録することができる。このような特殊な状況では、誰でもMTSに設定した以外のロールを使うことができてしまうというものだ。


 この2点は、くどいようだが英語版NT 4.0(SP4)を利用するときのみの問題だ。英語版のNTを利用することなどあまりないように思えるが、IMEのメモリリークなどを嫌がり英語版を使っている所も多いと聞く。確かにNT 4.0になってから、IMEなどがOSカーネルに近い位置に置かれてしまい、たとえばIMEを外そうと思っても、日本語版では不可能なのだ。そこで、英語版の登場ということになる。さらに、英語版だとSPをあてる時期も「日本語版SPが出たら」ということを指針とすることもできるように感じる。これは、日本語版SPなどでは、SPに対するQEFが今回のように当たっているときがあるからだ。
 さて、ActiveX DLLであるOracle Objects for OLEならば、MTSから使ってもなにか面白いことができるのではないかと思い、書き始めたが、結果的に思っていたようなことはできなかった。こうなったらMTSのオブジェクトプール機能だけでもOracle Objects for OLEからしゃぶり尽くすようなプログラムを作りたくなってくる。次回、予告を変更して、もう一度MTS with oo4oについて考察したい。「MTSとRDBMSのいい関係〜リベンジ編」だ!




サンプルプログラムのダウンロード  --- mts01.lzh(26KB)



VB Magazine ライブラリ | Visual Basic WorkGroup
int21 ホームページ | PCDN ホームページ


Copyright (c) 1998 int21 Corporation All Rights Reserved.
For questions or comments, please send mail to: pcdn@int21.co.jp