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

スポンサーリンク

Access VBAの「ロック」を制する者はマルチユーザーを制す:DAO.Recordsetの排他制御、極限の設計指針

多くのAccess開発者が陥る罠がある。「とりあえず動くから」と、デフォルトの排他制御設定を放置することだ。だが、マルチユーザー環境でその甘さは、いずれ「書き込みエラー」という名の悪夢となって帰ってくる。

今日は、DAO.Recordsetの`LockEdits`プロパティを軸に、「悲観的排他制御」と「楽観的排他制御」をどう使い分け、堅牢な業務アプリを構築するかを、プロの視点で伝授する。

1. なぜ「排他制御」の理解が不可欠なのか

Accessのバックエンド(Jet/ACEエンジン)における排他制御には2つの流派がある。

  • 悲観的排他制御 (Pessimistic Locking): レコードを開いた瞬間にロックをかける。競合は絶対に起こらないが、他人の作業を止め、システム全体を低速化させる。
  • 楽観的排他制御 (Optimistic Locking): 更新する直前までロックしない。競合が発生した時に初めてエラーを検知する。スケーラビリティは高いが、衝突時のハンドル(例外処理)が必須となる。

結論から言おう。 現代の業務アプリにおいて、無闇な悲観的ロックは「悪」だ。しかし、会計データのような厳密性が求められる箇所では必要になる。この使い分けをコードレベルで設計できるか否かが、エンジニアとしての格を決める。

2. 実践:DAO.Recordsetによる排他制御の制御

以下のコードは、保守性を担保しつつ、排他制御を明示的に切り替えるためのテンプレートだ。

‘ @description: 堅牢な排他制御を実装したDAO更新テンプレート
‘ @param: strSQL – 更新対象のクエリ
‘ @param: isPessimistic – Trueなら悲観的、Falseなら楽観的
Public Sub UpdateRecordSecure(strSQL As String, isPessimistic As Boolean)
Dim db As DAO.Database
Dim rs As DAO.Recordset

Set db = CurrentDb

‘ 楽観的排他制御: dbOpenDynasetのデフォルトはdbOptimistic
‘ 悲観的排他制御: dbPessimisticを指定
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset, , IIf(isPessimistic, dbPessimistic, dbOptimistic))

On Error GoTo ErrorHandler

If Not (rs.BOF And rs.EOF) Then
rs.Edit
rs!Status = “Processed”
rs.Update ‘ ここで確定(楽観的の場合はこの瞬間に競合チェック)
End If

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

ErrorHandler:
If Err.Number = 3186 Or Err.Number = 3218 Then ‘ ロックエラーの代表例
MsgBox “現在、他者がこのレコードを編集しています。後でもう一度試してください。”, vbCritical
Else
MsgBox “予期せぬエラー: ” & Err.Description, vbCritical
End If
Resume CleanExit
End Sub

このコードの「プロのこだわり」

  • IIfによる動的切り替え: ロックモードを引数で制御することで、ビジネスロジックに応じた柔軟な運用を可能にしている。
  • 明示的な定数: `dbPessimistic` / `dbOptimistic` を明示的に指定することで、コードを読む他者が「この箇所が排他制御のホットスポットである」と直感的に理解できるようにしている。
  • エラーハンドラの分離: 単なるエラーログではなく、排他エラー(3186/3218)を特定し、ユーザーに適切なアクションを促す仕様にしている。

3. 現場で生き残るための「鉄則」

① 「フォーム」と「VBAコード」の排他設定を混同するな

Accessのフォームには「レコードロック」プロパティがあるが、これはフォーム単位の設定だ。一方、VBAの`Recordset`は、プログラムが能動的に制御する「データベースの心臓部」である。プログラムで複雑な更新を行う場合は、フォームの設定をアテにせず、常にVBA側で排他制御を定義すること。

② 悲観的ロックは「短く」保て

悲観的ロックをかけている最中に、ユーザーへのメッセージボックス表示や、外部ファイルへの長時間出力を行ってはならない。ロックしたまま処理を中断すると、それはデッドロック(システム停止)への直行便だ。

③ 楽観的ロックは「例外処理」が全て

楽観的ロックを採用するなら、`Update`メソッドが失敗する確率を0にはできないことを前提とせよ。「更新失敗→競合発生→ユーザーへ現状データを再読み込みさせる」というフローを、例外処理の中に美しく組み込むことが、真に堅牢なプロダクションコードの姿だ。

最後に:エンジニアへの提言

Accessは「誰でも使える」ツールだが、プロの手にかかれば「エンタープライズ級のバックエンド」を隠し持った強力な武器に変貌する。

今回解説した排他制御の使い分けは、単なる知識ではなく、「多人数が同時に触るデータ」に対する敬意である。ユーザーが安心してデータを入力できる環境を作ることこそが、我々エンジニアの真の付加価値だ。

まずは、今書いているそのコードの`OpenRecordset`を見直してほしい。そこに、あなたのエンジニアとしての魂を刻み込んでくれ。

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