C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[11]: MDBの更新を即反映させたい


(過去ログ 39 を表示中)

[トピック内 17 記事 (1 - 17 表示)]  << 0 >>

■20351 / inTopicNo.1)  MDBの更新を即反映させたい
  
□投稿者/ 鶏唐揚 (179回)-(2008/06/09(Mon) 18:12:55)

分類:[VB.NET/VB2005] 

[DB]Access MDB
[VB]2005

お世話になっております。

早速ですが、サーバにおいてある1つのMDBを、別端末の2つのアプリから参照・更新等している状態です
ここで、Aが更新した内容を、1・2秒しないうちにBで抽出すると、
Aの更新が反映されていない状態です。これはMDBの欠点ということまではわかっていますが、
なんとか即座反映(もしくは更新されたことを知る)方法があればご教示ください。

引用返信 編集キー/
■20358 / inTopicNo.2)  Re[1]: MDBの更新を即反映させたい
□投稿者/ 魔界の仮面弁士 (763回)-(2008/06/09(Mon) 18:31:39)
No20351 (鶏唐揚 さん) に返信
> 早速ですが、サーバにおいてある1つのMDBを、別端末の2つのアプリから参照・更新等している状態です
> ここで、Aが更新した内容を、1・2秒しないうちにBで抽出すると、
> Aの更新が反映されていない状態です。これはMDBの欠点ということまではわかっていますが、
> なんとか即座反映(もしくは更新されたことを知る)方法があればご教示ください。

トランザクションを張っていないのでは無いでしょうか?
明示的に Commit しないと、非同期更新になってしまいますよ。

http://www.canalian.com/workshop/access/JetCache.html
引用返信 編集キー/
■20359 / inTopicNo.3)  Re[2]: MDBの更新を即反映させたい
□投稿者/ 鶏唐揚 (180回)-(2008/06/09(Mon) 18:36:59)
No20358 (魔界の仮面弁士 さん) に返信
> ■No20351 (鶏唐揚 さん) に返信
>>早速ですが、サーバにおいてある1つのMDBを、別端末の2つのアプリから参照・更新等している状態です
>>ここで、Aが更新した内容を、1・2秒しないうちにBで抽出すると、
>>Aの更新が反映されていない状態です。これはMDBの欠点ということまではわかっていますが、
>>なんとか即座反映(もしくは更新されたことを知る)方法があればご教示ください。
>
> トランザクションを張っていないのでは無いでしょうか?
> 明示的に Commit しないと、非同期更新になってしまいますよ。
>
> http://www.canalian.com/workshop/access/JetCache.html
すみませんそのあたりの情報提示を忘れていました…

トランザクションは張っています。更新SQL実行後に即コミットさせてます。
ただ、反映されるタイミングがバラバラで、即反映されるときもあるのです。
遅いときは2、3秒ほど…なお表ロックはシステム構成上、掛けるとまずいので
更新対象行にロックフラグ列を作って、それを見ています。

が、そのロックフラグさえも反映が遅れ、同時更新を行ってしまっている現状です。
引用返信 編集キー/
■20360 / inTopicNo.4)  Re[3]: MDBの更新を即反映させたい
□投稿者/ れい (631回)-(2008/06/09(Mon) 18:40:22)
No20359 (鶏唐揚 さん) に返信
> 遅いときは2、3秒ほど…なお表ロックはシステム構成上、掛けるとまずいので
> 更新対象行にロックフラグ列を作って、それを見ています。

このロックフラグがいけないのではないかと。

ロックフラグを更新するときに
トランザクションとかロックとか、
きちんと同期制御してますか?

引用返信 編集キー/
■20364 / inTopicNo.5)  Re[3]: MDBの更新を即反映させたい
□投稿者/ 魔界の仮面弁士 (764回)-(2008/06/09(Mon) 19:11:06)
2008/06/10(Tue) 12:34:35 編集(投稿者)

No20359 (鶏唐揚 さん) に返信
> 遅いときは2、3秒ほど…
明示的トランザクションを有効にしても同じ問題が起きるのであれば、
ライトキャッシュ側ではなく、リードキャッシュの問題かも知れませんね。

初期設定のまま運用しているのであれば、書き込み遅延はせいぜい 500ミリ秒ですが、
リードキャッシュのフラッシュ間隔は 5000 ミリ秒と比較的長めなので。

リードキャッシュの更新頻度を上げるために、一時的に、PageTimeout を減じてみては如何でしょうか。
(HKLM\Software\Microsoft\Jet\4.0 を修正すると他のアプリにも影響を与えてしまうので、
別のエントリで設定した方が良いでしょう)

> なお表ロックはシステム構成上、掛けるとまずいので
(既定の)ページロックモードを使っているという事でしょうか。
それとも、レコードロックモード?
引用返信 編集キー/
■20365 / inTopicNo.6)  Re[4]: MDBの更新を即反映させたい
□投稿者/ ネタ好き (409回)-(2008/06/09(Mon) 19:22:13)
既知の情報かもしれませんが、一応心当たりを書きます。
ロック機構は粒度が細かければ細かいほど、制御によるオーバーヘッドが高くなります。
しかし、粒度が荒すぎても並列性が下がるのでパフォーマンスが悪化する場合があります。
でも粒度が荒くても読み込みだけならば逆に効率がいいのでよく実験する必要があります。

引用返信 編集キー/
■20367 / inTopicNo.7)  Re[5]: MDBの更新を即反映させたい
□投稿者/ 鶏唐揚 (181回)-(2008/06/09(Mon) 20:03:34)
>(既定の)ページロックモードを使っているという事でしょうか。
>それとも、レコードロックモード?
私が入る前からあるシステムなのでどうなっているのかは定かではありません。
ただ、何も弄ってないとは思うので既定だと思います(でも排他制御すらされてないような気がする…)

すみませんあまり時間がないので質問を若干変えます。

排他制御をSQLで行うことは可能なのでしょうか。
調べていてもAccessの設定だとかそういうのばかりですが、
それだとクライアント側の設定をすることになるのでなんとか
プログラム内で排他制御を行いたいと思います。
テーブルロックでも問題ないようなロジックがちょっと浮かんできたので
テーブルロックでもOKとします。

#SQL文で LOCK TABLE *** ってのがありましたが使えませんでした…

#Open前に排他制御指定するっていうのも見かけたのですが、
それだと取得すらできなくなるので
更新時のみ排他制御したいと思います
引用返信 編集キー/
■20368 / inTopicNo.8)  Re[6]: MDBの更新を即反映させたい
□投稿者/ ネタ好き (410回)-(2008/06/09(Mon) 20:12:16)
No20367 (鶏唐揚 さん) に返信
SQL規格では SET TRANSACTION ISOLATION LEVEL 分離レベル
文でトランザクションの分離レベル(ロックの程度)を指定する事になっています。
しかし私の記憶が確かならAccess2000ではサポートされていませんでした。
引用返信 編集キー/
■20382 / inTopicNo.9)  Re[6]: MDBの更新を即反映させたい
□投稿者/ 魔界の仮面弁士 (766回)-(2008/06/10(Tue) 10:41:24)
No20367 (鶏唐揚 さん) に返信
> 排他制御をSQLで行うことは可能なのでしょうか。
できません。
排他制御できるのは、コネクションとレコードセットぐらいで、
それらはSQLから指定できるようにはなっていません。
(INSERT や UPDATE では制御できず、SELECT で取得したカーソルに対するロック制御になります)

> テーブルロックでもOKとします。
テーブルセット型レコードセットに対して、リードロック/ライトロック/リードライトロックを
かける事はできますが、ADO.NET ではそうした制御に対応できないので、それを行うとなると、
DAO を使う事になるでしょう(ADO でもロックできますが、DAO ほどの融通は利きません)。
使用するのは type:=dbOpenTable, options:=dbDenyWrite Or dbDenyRead あたりですね。

ただ、排他制御とリードキャッシュの問題は別物なので、先の URL や下記の URL などの
対処を組み込む必要はあるかも知れません。
http://support.microsoft.com/kb/191253/ja
引用返信 編集キー/
■20384 / inTopicNo.10)  Re[7]: MDBの更新を即反映させたい
□投稿者/ 鶏唐揚 (182回)-(2008/06/10(Tue) 11:13:34)
えー、まず真剣に返信してくださった皆様に、テンパってて情報欠落が著しかったこと・言ってることがコロコロ変わったをお詫びします。

猶予をもらったので詳しく調べてみました(昨日の時点では昨日が期限でした…)
MDBに詳しくないので変な表現があるかもしれませんがそこは突っ込んでください。

まず接続はSystem.Data.OleDBを使用しています
ConnectionStringは"Microsoft.Jet.OLEDB.4.0"となっています。

で、調べたところReadキャッシュが原因のような気がしてきました。
キャッシュをリフレッシュする方法を発見したのですが、JROを参照しないと
だめっぽいので、参照設定なしでリフレッシュする方法があればご教示願います。

最悪は重要なデータ取得時にDBをCloseしてOpenする方法を考えています
引用返信 編集キー/
■20385 / inTopicNo.11)  Re[8]: MDBの更新を即反映させたい
□投稿者/ はつね (774回)-(2008/06/10(Tue) 11:26:25)
はつね さんの Web サイト
No20384 (鶏唐揚 さん) に返信
> まず接続はSystem.Data.OleDBを使用しています
> ConnectionStringは"Microsoft.Jet.OLEDB.4.0"となっています

試していませんが、Max Buffer Sizeをゼロにしちゃうとかで改善しませんか?
http://msdn.microsoft.com/ja-jp/library/cc426819.aspx

あとは
Enable Fat Cursors
Fat Cursor Cache Size
あたり。

引用返信 編集キー/
■20387 / inTopicNo.12)  Re[8]: MDBの更新を即反映させたい
□投稿者/ やじゅ (445回)-(2008/06/10(Tue) 11:30:49)
No20384 (鶏唐揚 さん) に返信
> キャッシュをリフレッシュする方法を発見したのですが、JROを参照しないと
> だめっぽいので、参照設定なしでリフレッシュする方法があればご教示願います。
>

こんなとこですかね。

3.JROを用いる方法 魔界の仮面弁士さんのサイトですね。 
Set JE = CreateObject("JRO.JetEngine")
http://yaplog.jp/orator/monthly/200504/

キャッシュの更新
http://www.microsoft.com/japan/msdn/data/techmat/ado/dao2ado_8.aspx
引用返信 編集キー/
■20393 / inTopicNo.13)  Re[8]: MDBの更新を即反映させたい
□投稿者/ 魔界の仮面弁士 (767回)-(2008/06/10(Tue) 12:47:20)
No20384 (鶏唐揚 さん) に返信
> 調べたところReadキャッシュが原因のような気がしてきました。
もしそうならば、Page Timeout 設定時間の以上のウェイトをかけてから読み込めば、
キャッシュの問題はクリアされるかと思います。既定値では長すぎるので、
キャッシュのタイムアウト時間は短めに設定する必要があるでしょうけれども。


> JROを参照しないと
参照設定に加えずとも、レイトバインドで呼び出せますよ。

CreateObject("JRO.JetEngine").RefreshCache(conn)

ただ、その引数には(接続文字列では無く)ADODB.Connection が要求されますし、
JRO が ADO.NET に対しても有効であるという資料は見たことが無いので、
今回の目的で利用できるかどうかは未知数ですけれども。


> 接続はSystem.Data.OleDBを使用しています
ADO.NET で制御できるのは、プロバイダ固有の接続パラメータぐらいですね。

ただ、最近のバージョンの Jet OLE DB プロバイダだと、なぜか一部のプロパティ
("Jet OLEDB:Page Timeout"、"Jet OLEDB:Flush Transaction Timeout" など)が
ADO / ADO.NET に関わらず指定できなくなっている場合があるため、細かいパラメータは、
先述したレジストリ指定の方が良いかも知れません。

Dim cb As New OleDb.OleDbConnectionStringBuilder()
cb.Provider = "Microsoft.JET.OLEDB.4.0"
cb.DataSource = "c:\db1.mdb"
cb.Add("Jet OLEDB:Registry Path", "Software\MyCompany\MyApp\1.0")

上記のようにすると、キャッシュのフラッシュ間隔やバッファサイズなどを
HKEY_LOCAL_MACHINE\SOFTWARE\MyCompany\MyApp\1.0 から読み取られるようになります。


> 重要なデータ取得時にDBをCloseしてOpenする方法を考えています
その方法は DAO では有効ですが、OLE DB の場合はコネクション プーリングの
機構があるため、必ずしもフラッシュされるとは限らなかったりします。
ADO.NET が接続プールを有効にしているのかどうかは未検証ですが、もし有効で
ある場合には、接続文字列の一部を変更してから(大文字小文字の違いでも良い)
再 Open した方が良いかも知れません。
引用返信 編集キー/
■20396 / inTopicNo.14)  Re[9]: MDBの更新を即反映させたい
□投稿者/ 魔界の仮面弁士 (768回)-(2008/06/10(Tue) 13:24:52)
No20385 (はつね さん) に返信
> 試していませんが、Max Buffer Sizeをゼロにしちゃうとかで改善しませんか?

といっても、初期値がもともと 0 だったりします。
(正確には Max Buffer Size ではなく、Jet OLEDB:Max Buffer Size です)

これはレジストリでいえば、
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Jet 4.0\MaxBufferSize
に相当する設定項目です。

そもそも MaxBufferSize に 0 KBという指定はできません。0 は自動割当として扱われ、
この場合のキャッシュサイズは『メインメモリ÷ 4 + 2560(KB)』で算出される仕様です。
(なお、JET 3.5x では上限値が 13,824KB だそうです。4.0 の上限値は把握していませんが。)


で。Jet がライトキャッシュを更新するのは、
 (1) 最初の更新処理が行われた後、一定時間が経過したとき。(既定値:500ミリ秒)
 (2) 更新用バッファサイズを超過したとき。
のいずれかの条件を満たしたときです。
そして今回の MaxBufferSize とは、上記(2) に関する設定項目にあたります。

また、(1) に影響を与えるのは、レジストリ(括弧内は OLE DB)でいうところの
 FlushTransactionTimeout (Jet OLEDB:Flush Transaction Timeout)
 ExclusiveAsyncDelay (Jet OLEDB:Exclusive Async Delay)
 SharedAsyncDelay (Jet OLEDB:Shared Async Delay)
のエントリです。(FlushTransactionTimeout が最優先されます)


この辺りの設定は、ADO.NET の接続パラメータに指定できないため、
レジストリ側で設定する事になるでしょう。(No20393 参照)
http://support.microsoft.com/kb/318161/en-us


> あとは
> Enable Fat Cursors
> Fat Cursor Cache Size
> あたり。
これらは、ADO.NET では使用できないため、ADO を使うことになりますね。
引用返信 編集キー/
■20397 / inTopicNo.15)  Re[9]: MDBの更新を即反映させたい
□投稿者/ 鶏唐揚 (183回)-(2008/06/10(Tue) 13:33:01)
はつね さん、やじゅ さん、魔界の仮面弁士さん
返信ありがとうございます。
レジストリの変更と接続時のパラメータは、他に影響があると取り返しつかなくなるので
避けたいと思います。

JROの件ですが、OleDbConnetionをそのまま渡したら案の定InvalidCast例外が発生しました。

ので、工数の関係上Open/Closeで対処したいと思います。
コネクションプーリングの情報ありがとうございます。
引用返信 編集キー/
■20437 / inTopicNo.16)  Re[10]: MDBの更新を即反映させたい
□投稿者/ 鶏唐揚 (185回)-(2008/06/10(Tue) 17:10:50)
重要データ取得前にDBをClose後、再Openをすることで今のところ順調に動作しています。

なんとなく力技のような気がしますが、今回はこれで解決とさせていただきます。
皆さんの貴重なご意見は今後の参考にさせていただきます。

#でももうMDB扱いたくないw
解決済み
引用返信 編集キー/
■20440 / inTopicNo.17)  Re[11]: MDBの更新を即反映させたい
□投稿者/ ぽぴ王子 (386回)-(2008/06/10(Tue) 17:22:43)
ぽぴ王子 さんの Web サイト
No20437 (鶏唐揚 さん) に返信
> 重要データ取得前にDBをClose後、再Openをすることで今のところ順調に動作しています。
>
> なんとなく力技のような気がしますが、今回はこれで解決とさせていただきます。
> 皆さんの貴重なご意見は今後の参考にさせていただきます。
>
> #でももうMDB扱いたくないw

確かにペリー・ローダンとAccessだけは手を出すなと死んだじいちゃんも言ってましたっけ。
とりあえず
> サーバにおいてある1つのMDBを、別端末の2つのアプリから参照・更新等している状態
という仕様を決めた人を恨むぐらいしか。

気合いと時間と手間が許せば、mdbファイルに直接アクセスするのではなくもう1個プログラムを
作って、端末からの要求に従ってそいつにだけアクセスさせるというやり方もとれたかもしれませんね。
ゲートウェイというか、Webサービス的というか。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -