Access + SQL Server 2022 + ODBC Driver 18 環境で「データの競合」が頻発した件と rowversion による解決

ACCESS

Access フロントエンド + SQL Server バックエンド環境において,SQL Server 2022 へ移行後,「データの競合」エラーが頻発する現象が発生した。

発生した現象

Access フォームやリンクテーブル編集時に,以下のエラーが頻発。

このレコードは,他のユーザーによって変更されています。

発生条件はかなり単純で,

  • サブフォームへフォーカス移動
  • 単純な UPDATE
  • テーブル直接編集

でも発生した。

環境

  • Access フロントエンド
  • SQL Server 2022
  • ODBC Driver 18 for SQL Server
  • SQL Server リンクテーブル
  • 主キーあり
  • trigger なし

テーブルには DEFAULT(GETDATE()) が設定されていた。

当初疑ったもの

まず以下を疑った。

  • サブフォーム自動保存
  • DEFAULT(GETDATE())
  • datetime 精度
  • ODBC Driver 18
  • ダイナセット(矛盾を許す)
  • trigger

しかし,単純なテーブル編集でも発生したため,「更新対象行の識別」に問題がある可能性が高くなった。

原因

Access は SQL Server 更新時に,

「自分が開いた行」と「現在のDB上の行」

を比較して楽観ロックを行っている。

しかし rowversion 列が無い場合,

  • datetime
  • NULL
  • 自動更新列
  • DEFAULT値

などを含めて比較している可能性があり,ODBC Driver 18 環境では競合判定が厳格化しているようだった。

結果として,

実際には他ユーザー更新ではないのに「競合」と判定

されていた。

解決方法

SQL Server テーブルへ rowversion 列を追加。

ALTER TABLE dbo.T_HOGE
ADD タイムスタンプ rowversion NOT NULL;

追加後,競合エラーは解消。

補足

SSMS 上では列型が timestamp と表示されるが問題ない。

SQL Server では:

  • timestamp = 旧名称
  • rowversion = 推奨名称

という関係であり,内部的には同じ型。

なお,これは日時ではなく,自動更新される binary(8) のバージョン番号である。

実務上の所感

Access + SQL Server 環境では,特に以下の構成で rowversion の重要性が高いと感じた。

  • SQL Server 2019 / 2022
  • ODBC Driver 17 / 18
  • Access 旧資産
  • DEFAULT値あり
  • 自動保存あり

Access 側に問題が見えていても,実際には SQL Server 側の rowversion 不在が原因となっているケースがある。

コメント

スポンサーリンク
タイトルとURLをコピーしました