表題の解決策を検討しています。
【開発環境】
windowsXP sp2 VC++6.0
【データソースへの接続方法】
MFC CRecordsetでデータソースに接続。
【テスト環境】
PC1 windowsXP sp2
データベースを設置(MySQLコミュニティサーバ5.0で構築)
PC2 windowsXP sp2
データベースに接続するAPが稼動(接続にはMyODBC3.51を経由)
PC1とPC2は、社内LANに接続されている。
【現象】
APからデータベースへの接続直後にPC1のUTPを切断すると、APがフリーズする。
【調査状況】
プログラムをデバッガで追うとCRecordset::Open()内で::SQLExecute()を
コールしてまま制御が返ってきていません。
CDatabase、CRecordsetに対するタイムアウト値の設定などを行いましたが無効でした。
推測ですが、ODBCドライバの中でロックしてしまい、アプリケーション側の設定やらタイムアウト値は効いていないように思えます。
色々ネットであたっているのですが、一致する現象が見つかりません。
原因、回避策、またはこの状況に陥ってしまった場合の脱出策など情報をお持ちの方ご教授下さい。宜しくお願いします。
スレッドまわしてその中でアクセスしてみてはいかがでしょうか。
少なくともハングアップはなくなると思うので
(ドライバ内で無限ループしてたりしたら厄介ですが)
再試行、再起動、ログ出力などの勧告をユーザーに出せると思います。
非同期でアクセスできればそれが一番いいのですが・・・
そだ様 ご教授ありがとうございます。
CRecordset::Cansel()は使用したことありますか?
MSDNを見る限り、別スレッドからデータソースに対して
キャンセルを要求が出来るようです。実験してみると
Cansel()をコールしてから1分後位に制御が返ってきました。
ただ、ドライバの中でネイティブアクセスしている箇所で
ロックしていた場合は、無効なのかもしれません。
その辺のタイミングはもう少し実験してみようと思います。
もし何かご存知でしたらご教授下さい。
別案として、別プロセスにすることも検討したのですが、
イレギュラーなケースへの対応でそこまで大掛かりに
したくないということもありまして見送りました。
今のところ、CRecordset::Cansel()の案で駄目なら、
ご教授頂いた、ユーザへ勧告を出す方法にしたいと思います。
余談ですが、この手の情報はネット上でも少ないのですね。
同じ現象で困っている人は沢山居ると思っていたのですが。
>CRecordset::Cansel()
使用したことありません。でも
関数が設けられているなら無理にスレッドを止めずに
こちらを使ったほうがよさそうですね。
>余談ですが、この手の情報はネット上でも少ないのですね。
>同じ現象で困っている人は沢山居ると思っていたのですが。
個人でそこまで想定してテストしないからでは?
通信やるときに物理層での切断自体はあり得る話なんですけどね・・・
そだ様
その後の報告がだいぶ滞っており、大変失礼致しました。
CRecordset:Cancel()を使ったら制御が返ってきたように見えていた
のですが、実際には無効のようでした。ODBCのAPIをコールした時に
LAN切断するタイミングによって一定時間後に制御が返る場合と
返らない場合が存在するようです。CRecordset:Cancel()を使って
制御が戻ったと思ったのは前者のタイミングのようでした。
後者のタイミングでテストすると制御は返りませんでした。
ODBCの中でネイティブアクセスしている部分でロックしているのかも
知れませんが、そこまでは調査していません。
ODBCを使うのは要求仕様ですので、お客さんには「そういうものです」
というレベルで理解して頂きました。対応策としてはユーザに再起動/
再試行を促すことになりました。
そだ様
貴重なご意見ありがとうございました。大変助かりました。
ツイート | ![]() |