7

私は、ADO.NETベースのWebサイトを構築するチームの一員です。データベースの開発コピーを同時に動作させる複数の開発者と自動テストツールが存在する場合があります。

スナップショット分離レベルを使用します。これは、私の知る限り、楽観的同時実行性を使用します。ロックするのではなく、影響を受ける行が他のパーティによって変更された場合にトランザクションをコミットしようとすると、最高のものを期待して例外をスローします。トランザクション。

スナップショット分離レベルを使用するには、次を使用します。

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;

およびC#の場合:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);

IsolationLevelスナップショットは、私たちも試したが現在使用していないReadCommittedスナップショットと同じではないことに注意してください。

開発者の1人がデバッグモードに入り、.NETアプリを一時停止すると、開発者はデバッグ中にアクティブなトランザクションとの接続を保持します。さて、これは問題ではないと思います-結局のところ、すべてのトランザクションはスナップショット分離レベルを使用しているので、一時停止されたトランザクションはロックを保持していないため、1つのトランザクションが一時停止されている間、他のトランザクションは正常に続行できるはずです。もちろん、一時停止されたトランザクションが完了すると、競合が検出される可能性があります。しかし、他の開発者や自動テストが妨げられることなく続行できる限り、それは許容されます。

ただし、実際には、デバッグ中に1人のユーザーがトランザクションを停止すると、スナップショット分離レベルを使用しているにもかかわらず、同じ行にアクセスしようとする他のすべてのDBユーザーがブロックされます。

なぜこれが発生するのか、および/または真の楽観的(非ブロッキング)並行性を実現する方法を誰かが知っていますか?

決議(私にとっては残念なことです)Remus Rusanuは、作家は常に他の作家をブロックしていると述べました。これはMSDNによってバックアップされています-それは完全には出てこないのですが、リーダーライターロックの回避について言及しているだけです。つまり、私が望む動作はSQLServerに実装されていません。

4

2 に答える 2

8

SNAPSHOT 分離レベルは、すべての分離レベルと同様に読み取りのみに影響します。書き込みはまだお互いをブロックしています。表示されているものが読み取りブロックであると思われる場合は、さらに調査し、ブロックが発生するリソースの種類とリソース名を確認する必要があります ( sys.dm_exec_requests の wait_type とwait_resource )。

開発者が何分間もデバッガーを凝視するシナリオをサポートするためにコードを変更することはお勧めしません。このシナリオが本番環境で繰り返される可能性がある (つまり、クライアントがハングする) と思われる場合は、話は別です。目的を達成するには、書き込みを最小限に抑え、トランザクションの最後にすべての書き込みを、戻る前にコミットする 1 回の呼び出しで実行する必要があります。この方法では、クライアントは X ロックを長時間保持できません (X ロックを保持している間はハングできません)。実際には、これを実行するのは非常に難しく、データ アクセス コードの記述方法について開発者側で多くの規律が必要です。

于 2009-06-25T14:27:09.127 に答える
2

ある開発者がトランザクションを一時停止したときのロックを見たことがありますか? また、スナップショット分離レベルをオンにするだけではあまり効果がありません。ALLOW_SNAPSHOT_ISOLATION を ON に設定しましたか?

手順は次のとおりです。

ALTER DATABASE <databasename>
SET READ_COMMITTED_SNAPSHOT ON;
GO

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

データベースでスナップショット分離が有効になったら、開発者とユーザーは、トランザクションをこのスナップショット モードで実行するように要求する必要があります。これは、ADO.NET トランザクション オブジェクトのクライアント側ディレクティブによって、または次のステートメントを使用して Transact-SQL クエリ内で、トランザクションを開始する前に行う必要があります。

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

ラージ

于 2009-06-25T14:24:22.593 に答える