2

シナリオ:
ラッパーTransactionScope(TransactionScopeOption.Required)内に埋め込まれたTransactionScope(TransactionScopeOption.Suppress)クエリ。「Suppress」クエリの前に、ラッパー「Required」TransactionScopeに関連付けられた別のクエリがあります。

これらの2つのクエリは、1つのテーブルでのみ重複します。前の「必須」クエリはテーブルに挿入し、後者の「抑制」クエリはテーブルから選択します。これがどれほど愚かであるか、そして「抑制」クエリがロックされていない行のみを読み取るため、新しく挿入された結果が含まれないという事実を無視してください。

動作:
私が見ている動作は、テーブル内に行がある場合、挿入が成功し、次に選択がロック解除された行を読み取り、次に進むというものです。ただし、テーブルが空の場合、挿入は成功しますが、選択は挿入によってブロックされているためスタックします。

質問:
私が取得しようとしているのは、このシナリオでロックがどのように追跡されているかについての概念的な理解です。以前は、テーブルのロックを、テーブルがロックまたはロック解除されたビットトグルの一種であると考えていましたが、NOTEXISTSを使用したCASEステートメントのようなもののようです。ロックされていない行がない場合、テーブルはロックされていませんが、テーブルはロックされていますが、その中のすべての行は現在ロックされた状態です。

私が見つけたすべてのことは、実際にはさまざまなレベルのロック(テーブル、行、ページなど)があることを示していますが、テーブルが空で行ロックが存在する場合に明示的に述べているものは見つかりません挿入されるデータでは、テーブルロックが暗示されます。当初、Selectが単にNullを返すことを期待していましたが、これは私が考えた動作ではないため、専門家に連絡して、誰かが私に決定的な理解を与えることができるかどうかを確認します。

注:
RDBMS:SQL Server 2012
.NET Framework:4.0
コアの動作:挿入前にテーブルにレコードが存在する場合、両方のクエリは成功しますが、挿入前にテーブルが空の場合、選択は挿入によってブロックされます。

テーブル:

Create Table Random(ID Int Identity, Word Varchar(50), TimeInserted DateTime)

クエリの挿入:

Insert Random(Word, TimeInserted)
Select 'Word', GetDate()

クエリを選択します。

Select Max(TimeInserted)
From Random
Where Word Like 'A%'
4

1 に答える 1

1

TransactionScopeのデフォルトのIsolationLevelは「Serializable」です。Msdnによると、この分離レベルでは、「揮発性データは読み取ることはできますが、変更することはできず、トランザクション中に新しいデータを追加することはできません」。「シリアル化可能」は非常にデッドロックが発生しやすいです。

SQLTransactionのデフォルトのIsolationLevelはReadCommittedです。このようにトランザクションスコープを宣言してみてください

using (var scope = new System.Transactions.TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TransactionManager.MaximumTimeout}))

それはあなたの問題を解決するかもしれません。

MSDNの詳細:

最高の分離レベルであるSerializableは、中断のあるトランザクションに対する高度な保護を提供しますが、他のトランザクションがデータを操作できるようになる前に、各トランザクションが完了する必要があります

于 2013-02-20T19:53:28.977 に答える