0

過去からの爆発... SQL 2005 サーバーに常駐するデータの管理に使用される老朽化した Access 2000 adp を管理する任務を負いました。データフォームの 1 つで、フィールドを変更してその変更をデータベースに保存しようとすると、約 1 分後にタイムアウトします。タイムアウト制限を増やしても、タイムアウト エラー メッセージの表示が遅くなるだけです。互換性を確保するために、通常のトラブルシューティングをすべて実行しました (たとえば、この SO の質問を参照してください)。

セットアップは次のとおりです。フォームはレコード セットにバインドされます (SELECT * FROM table_nameクエリとしてデータベースから読み取られます。結果セットのサイズは、フォームに設定されたフィルターによって異なりますが、通常、結果は約 200 レコードになります (それほど多くはありません)。データ...) フォームの一部のフィールドは、関連付けられたイベント ハンドラーで自動保存をトリガーします。これは次のようになります。

Private Sub EndDate_Exit(Cancel As Integer)
     some checking goes here...
     ...
     DoCmd.RunCommand acCmdSaveRecord
End Sub

コードが実行されるたびにDoCmd.RunCommand acCmdSaveRecord、タイムアウト エラーが発生するまで ADP がフリーズします。もう少し掘り下げて、SQL Server のアクティビティ モニターを調べました。は、変更されたデータを保存するためにステートメントをサーバーに返しますacCmdSaveRecordUPDATEステートメント自体は、基になるテーブルの主キーに基づいて MS Access によって自動的に作成されますが、これは正しく定義されているようです。ただし、更新は、上記SELECTのクエリに対応する実行中のステートメントによってブロックされます。SELECT * FROM table_name

これはデッドロックにつながります: ユーザーの変更により がトリガーされ、実行中UPDATEの によってブロックされますSELECT(これは、編集中のフォームから発生したように見えます)。どうすればこれを回避できますか?

私たちが試したこと:

  1. ステートメントを削除DoCmd.RunCommand acCmdSaveRecordし、コードに置き換えましたMe.Dirty = False。これにより、上記とまったく同じ動作が発生します。
  2. 完全なものを削除しacCmdSaveRecord、組み込みの Access メニューを使用して変更を保存しました。これは #1 と同等の機能であり、まったく同じ動作になります。
  3. acCmdSaveRecord呼び出しを、特定のフィールドへの変更を保存するストアド プロシージャに置き換えます。GUI( を呼び出す保存ボタンacCmdSaveRecord)からレコード全体を保存すると同じデッドロックが発生することを除いて、うまく機能します。
  4. フォームに関連付けられた結果セットのサイズを数レコードに減らしました。奇妙なことに、まったく同じ動作を示します。
4

1 に答える 1

1

SERIALIZABLEある時点で、接続のトランザクション分離レベルを に設定したようです。詳細については、「 SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。該当する抜粋を次に示します (強調を追加)。

シリアライズ可能

以下を指定します。

  • ステートメントは、他のトランザクションによって変更されたがまだコミットされていないデータを読み取ることはできません。

  • 現在のトランザクションが完了するまで、他のトランザクションは現在のトランザクションによって読み取られたデータを変更できません。

  • 他のトランザクションは、現在のトランザクションが完了するまで、現在のトランザクションのステートメントによって読み取られるキーの範囲に入るキー値を持つ新しい行を挿入できません。

範囲ロックは、トランザクションで実行される各ステートメントの検索条件に一致するキー値の範囲に配置されます。これにより、他のトランザクションは、現在のトランザクションによって実行されるステートメントのいずれかに該当する行を更新または挿入できなくなります。これは、トランザクション内のいずれかのステートメントが 2 回目に実行される場合、同じ行セットを読み取ることを意味します。範囲ロックは、トランザクションが完了するまで保持されます。これは、キーの範囲全体をロックし、トランザクションが完了するまでロックを保持するため、分離レベルの中で最も制限的です。同時実行性が低いため、このオプションは必要な場合にのみ使用してください。このオプションは、トランザクション内のすべての SELECT ステートメントのすべてのテーブルに HOLDLOCK を設定するのと同じ効果があります。

于 2011-11-08T17:21:18.917 に答える