【テクニカル・上級編】DAO.Recordsetの「LockEdits」プロパティによる、悲観的排他制御と楽観的排他制御の使い分け – Access VBA解析バイブル

スポンサーリンク

Access VBAの深淵:DAO.Recordsetにおける「LockEdits」の冷徹な選択

Access開発の現場において、マルチユーザー環境でのデータ競合は、避けては通れぬ「亡霊」のような存在だ。特に、`DAO.Recordset`における`LockEdits`プロパティの制御を疎かにすることは、システム全体をデッドロックの迷宮へ引きずり込む行為に等しい。

多くの初心者はデフォルト設定のまま放置するが、我々エンジニアが対峙するのは、数千人の同時接続と、ネットワークの微細な遅延が引き起こす「不可解な不整合」である。今日は、この排他制御の極致について、実戦的な視点から解剖する。

1. 悲観的排他制御(Pessimistic Locking)の呪縛と恩恵

`Recordset.LockEdits = True` を選択するということは、レコードを編集するその瞬間に、他者のアクセスを物理的に遮断することを意味する。

  • メリット: データの整合性は保証される。`Update`を実行するまで、他のトランザクションは当該レコードに触れられない。
  • デメリット: ネットワークの輻輳や、ユーザーが編集画面を開いたまま離席した瞬間、システムは「停止」する。

【極限の知見】
このモードは、厳密な会計処理や在庫引き当てなど、「絶対に競合を許さない」というビジネスロジックが存在する場合にのみ使用すべきだ。それ以外でこれを使用するのは、ただの怠慢である。

2. 楽観的排他制御(Optimistic Locking)という「賭け」

`LockEdits = False` と設定すれば、排他は`Update`メソッドを実行する直前の、ミリ秒単位の瞬間のみに行われる。

  • メリット: ユーザーの操作感は極めて軽快。デッドロックの発生確率は極限まで低減される。
  • デメリット: 「更新しようとしたら、既に誰かが変更していた」という例外処理を自力でハンドリングしなければならない。

3. 実践コード:堅牢な排他制御の実装

現場で通用するコードとは、エラーを握りつぶすものではなく、競合を「想定内」として設計されたものだ。以下に、楽観的排他制御をベースにした、堅牢な更新パターンを示す。

‘ 伝説的な堅牢性を備えたレコード更新処理のテンプレート
Public Sub SecureUpdate(ByVal lngID As Long, ByVal strNewValue As String)
Dim db As DAO.Database
Dim rs As DAO.Recordset

Set db = CurrentDb
‘ パフォーマンス最適化のため、必要な列のみ抽出
Set rs = db.OpenRecordset(“SELECT FROM T_Master WHERE ID = ” & lngID, dbOpenDynaset)

If Not rs.EOF Then
On Error GoTo HandleError

‘ 楽観的排他制御を採用
rs.LockEdits = False

rs.Edit
rs!ValueColumn = strNewValue
rs.Update

End If

CleanExit:
‘ オブジェクトの明示的解放:メモリリークは許されない
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set db = Nothing
Exit Sub

HandleError:
‘ 3020: 更新または削除の競合が発生した場合のハンドリング
If Err.Number = 3020 Then
MsgBox “誰か他のユーザーが更新中です。少し待ってから再試行してください。”, vbCritical
Else
MsgBox “予期せぬエラー: ” & Err.Description
End If
Resume CleanExit
End Sub

4. シニアエンジニアのための「隠し味」

A. ネットワーク越しでの戦い方

AccessのバックエンドがSQL Server等のRDBMSである場合、`LockEdits`の挙動はDAOの透過層を通じてドライバーに依存する。この時、`ODBCDirect`や`Pass-Through`クエリによる「楽観的制御」を検討せよ。DAOの`LockEdits`に頼り切るのではなく、SQLの`WHERE`句でバージョン管理(タイムスタンプ比較)を行うのが、現在の企業システムにおける「正解」である。

B. APIを用いた強制解放

極めて稀だが、ゾンビ化したロックを強制解除する必要がある場合、Windows APIの`NetFileClose`(サーバー上のファイルハンドル操作)を呼び出すという選択肢もある。ただし、これは劇薬であり、データ破損のリスクを伴うため、最終手段として封印しておくべきだ。

C. メモリ管理の鉄則

`Set rs = Nothing` を怠ることは、Accessのガベージコレクションを信用するという「慢心」である。特に大規模なループ処理内でこれを行うと、メモリ断片化により`Update`処理のパフォーマンスが徐々に劣化していく。必ず `Close` してから `Nothing` を代入せよ。

結び:エンジニアとしての矜持

VBAはレガシーと言われるが、そのオブジェクトモデルは極めて洗練されている。`LockEdits`の使い分け一つに、そのエンジニアが「ユーザーの利便性」と「データの整合性」のどちらに重きを置いているかが如実に表れる。

ツールに振り回されるのではなく、ツールの仕様を掌の上に転がすこと。それが、この過酷な現場で生き残る唯一の術である。さあ、次はどのプロパティを解剖しようか?

タイトルとURLをコピーしました