Access2003 ファイルの共有ロック数が制限を超えています (Error 3052)

お客さんのデータベースでエラーが起きた。

現金出納帳なのだが、残高計算をする時に以下のエラーが発生して止まってしまった。

前回までは問題なかったのに・・・なぜ?

これまでのモジュール

これまでは、以下のような感じで「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 で トランザクション制御を開始します。

これを最終データまで行います。

 

はぁ、これにて何とか解決しました。

よかった、よかった・・・。

コメント