【実務・中級編】DAO.RecordsetのLockEditsプロパティによる悲観的排他制御の最適化 – Access VBA解析バイブル

スポンサーリンク

【Access VBA】DAO.RecordsetのLockEditsによる「悲観的排他制御」を極める

Access開発において、マルチユーザー環境での「更新競合」を甘く見ているエンジニアは、いずれ致命的なデータ不整合という名の墓穴を掘ることになる。

多くの初心者は、「Accessが勝手にロックしてくれるから大丈夫」という幻想を抱いている。しかし、伝説的なシステムを構築したければ、DAO.Recordsetの`LockEdits`プロパティを支配し、排他制御のタイミングを自ら設計しなければならない。

今回は、Access VBAにおける「悲観的排他制御」の最適解を伝授する。

1. なぜ「悲観的排他制御」が必要なのか?

排他制御には大きく分けて「楽観的」と「悲観的」がある。

  • 楽観的排他制御: 更新時にのみ競合をチェックする。スループットは高いが、競合時の再試行ロジックが煩雑になる。
  • 悲観的排他制御: レコードを編集した瞬間にロックをかける。「編集中に他人に割り込まれない」という最強の保証がある。

Accessにおける`LockEdits = True`は、まさにこの悲観的排他制御の旗印だ。レコードに触れた瞬間に共有ロックをかけ、ユーザーが「編集して保存する」までの間、他者の書き込みを弾く。この挙動を理解せずに大規模ツールを組むのは、ブレーキのない車で高速道路を走るようなものだ。

2. LockEditsを制御する「プロダクションコード」

単に `LockEdits = True` と書けばいいわけではない。大切なのは「ロックをかけた後の例外処理」「トランザクションの適切なスコープ」だ。

以下のコードは、実務でそのまま利用可能な、堅牢な更新処理のテンプレートである。

‘ ——————————————————————
‘ @brief: 悲観的排他制御を用いた安全なレコード更新処理
‘ @param: targetID – 更新対象のID
‘ ——————————————————————
Public Sub SafeUpdateRecord(ByVal targetID As Long)
Dim db As DAO.Database
Dim rs As DAO.Recordset

Set db = CurrentDb
‘ レコードセットを開く際、必ずテーブル定義を意識したフィルタをかける
Set rs = db.OpenRecordset(“SELECT FROM T_Master WHERE ID = ” & targetID, dbOpenDynaset)

‘ 【核心】悲観的排他制御を明示的に指定
rs.LockEdits = True

On Error GoTo ErrHandler

If Not rs.EOF Then
rs.Edit ‘ ここで悲観的ロックが走る

‘ — ビジネスロジックをここに記述 —
rs!Status = “Processed”
rs!LastUpdated = Now
‘ ———————————

rs.Update ‘ 正常に更新完了
End If

Cleanup:
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set db = Nothing
Exit Sub

ErrHandler:
‘ 3260: 他のユーザーがロック中であるというエラーコード
If Err.Number = 3260 Then
MsgBox “現在、このレコードは他ユーザーが編集中です。後ほど再試行してください。”, vbCritical
Else
MsgBox “予期せぬエラー: ” & Err.Description, vbCritical
End If
Resume Cleanup
End Sub

3. 伝説的アーキテクトからの「警告」

このコードを実装する上で、必ず守らなければならないルールが3つある。

1. ロック時間を最小化せよ

`rs.Edit` から `rs.Update` までの間は、データベースの扉を閉ざしている状態だ。この間に重い外部API呼び出しや、ユーザーの入力を待つような処理(`InputBox`など)を挟んではならない。ロック時間が長引けば、システム全体がデッドロックの温床になる。

2. `dbOpenDynaset` を明示せよ

デフォルトの挙動に頼るな。`dbOpenDynaset` を指定することで、Jet/ACEエンジンに対し、排他制御を伴う動的なレコードセットであることを明示的に伝える。これがパフォーマンスの安定性を決める。

3. ネットワーク共有環境の宿命を理解せよ

Accessのバックエンドが共有フォルダ上にある場合、排他制御はファイルレベルの「.laccdb」に依存する。ネットワークの瞬断はロックの解放を妨げる可能性がある。そのため、`On Error`での例外ハンドリングは、単なるバグ除けではなく、「ビジネス上の整合性を守る防波堤」であると心得るべきだ。

結論:コードは「意図」を語るべき

優れた自動化エンジニアとは、ただ動くコードを書く者ではない。「いつ、なぜロックがかかり、どこで解放されるのか」を論理的に設計できる者だ。

`LockEdits`を正しく使いこなせば、ユーザーは安心して業務に集中できる。Accessという泥臭い環境であっても、設計次第で堅牢なエンタープライズ級のアプリケーションは作れる。

さあ、あなたのコードから「曖昧なロック」を排除し、信頼性の高いシステムを構築してほしい。それができるのは、この技術を理解したあなただけだ。

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