お客さんのデータベースでエラーが起きた。
現金出納帳なのだが、残高計算をする時に以下のエラーが発生して止まってしまった。
前回までは問題なかったのに・・・なぜ?
これまでのモジュール
これまでは、以下のような感じで「Q_現金出納帳残高計算」を使って残高を計算、書き込みしていた。
Option Compare Database Option Explicit Public Sub Zandaka() Dim Cnn As Connection Dim Rst As New ADODB.Recordset Dim Res As Byte Dim Zandaka As Long Set Cnn = CurrentProject.Connection Set Rst = New ADODB.Recordset Rst.Open "Q_現金出納帳残高計算", Cnn, adOpenKeyset, adLockOptimistic Zandaka = 0 '変数初期化 DoCmd.Hourglass True Do Until Rst.EOF Zandaka = Zandaka + Nz(Rst!収入) - Nz(Rst!支出) Rst!残高 = Zandaka Rst.Update Rst.MoveNext Loop DoCmd.Hourglass False Rst.Close Set Rst = Nothing Cnn.Close Set Cnn = Nothing End Sub
マイクロソフトのページに解説があった
「ファイルの共有ロック数が制限を超えています (Error 3052)」で検索してみるとマイクロソフトのページに解説がある。
- 現象
1 人以上のユーザーが、マルチユーザー環境で多数のトランザクションを処理すると、トランザクションが失敗し、次のエラー メッセージが表示されることがあります。
ファイルの共有ロック数が制限を超えています- 原因
このエラーは、トランザクションを実行するために必要なロックの数が、ファイルごとの最大ロック数を超えた場合に発生します。- 回避策
警告 : レジストリ エディタまたは別の方法を使用してレジストリを誤って変更すると、深刻な問題が発生することがあります。最悪の場合、オペレーティング システムの再インストールが必要になることがあります。マイクロソフトは、レジストリの変更により発生した問題に関しては、一切責任を負わないものとします。レジストリの変更は、自己の責任において行ってください。この問題を回避するには、ファイルごとの最大ロック数を増やします。これを行うには、以下のいずれかの方法を実行します。方法 1 : MaxLocksPerFile レジストリ キーを設定して、ファイルごとの最大ロック数を増やす方法 2 : SetOption メソッドを使用して MaxLocksPerFile の値を一時的に変更する
なのだそうだ。
レジストリ「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Jet 4.0」の「MaxLocksPerFile」値の規定値は「9,500」。
お客さんのデータは 9,535件。
このために起こったエラーなのか???
どちらにしてもレジストリー操作すると、今後ハードが変わったりした時に困るのでトランザクションで処理してみた。
トランザクションで処理
こんな感じに変更しました。
Option Compare Database Option Explicit Public Sub Zandaka() Dim Cnn As Connection Dim Rst As New ADODB.Recordset Dim Res As Byte Dim Zandaka As Long Dim intTranCnt As Integer Set Cnn = CurrentProject.Connection Set Rst = New ADODB.Recordset Rst.Open "Q_現金出納帳残高計算", Cnn, adOpenKeyset, adLockOptimistic Zandaka = 0 '変数初期化 intTranCnt = 0 DBEngine.BeginTrans DoCmd.Hourglass True Do Until Rst.EOF Zandaka = Zandaka + Nz(Rst!収入) - Nz(Rst!支出) Rst!残高 = Zandaka Rst.Update Rst.MoveNext intTranCnt = intTranCnt + 1 If intTranCnt = 5000 Then DBEngine.CommitTrans DBEngine.BeginTrans intTranCnt = 0 End If Loop DBEngine.CommitTrans DoCmd.Hourglass False Rst.Close Set Rst = Nothing Cnn.Close Set Cnn = Nothing End Sub
トランザクションとは、テーブルへのレコードの追加・更新・削除など、データベースに対する操作を管理するための、一つの処理単位です。
今回の場合、以下のような流れです。
DBEngine.BeginTrans で トランザクション制御を開始します。
5,000 件の残高を計算したら、DBEngine.CommitTrans で 5,000 件分の変更を保存します。
で、各種変数を初期化して、再度 DBEngine.BeginTrans で トランザクション制御を開始します。
これを最終データまで行います。
はぁ、これにて何とか解決しました。
よかった、よかった・・・。
コメント