1

次のトランザクションがあります:

  Desc d = new Desc();
  d.Descr = "new";

  _sess.Transaction.Begin();

  _sess.SaveOrUpdate(d);

  var desc = _sess.CreateCriteria(typeof(Desc)).List<Desc>();

  _sess.Transaction.Commit();

このトランザクションは次のクエリを実行します。

BEGIN TRANSACTION

INSERT

SELECT 

COMMIT TRANSACTION

このコードを 2 つのプロセスで実行すると、デッドロックが発生します。

1工程

INSERT を実行してキーをロックする

2 プロセス

INSERT を実行してキーをロックする

1 プロセスが SELECT の実行を希望し、TIMEOUT STATE で渡す 2 プロセスが SELECT の実行を希望し、TIMEOUT STATE で渡す

結果: デッドロック

BD: MS SQL Server 2008 R2

2 つの質問:

  1. トランザクションに含まれるすべてのテーブルに UPDATE LOCK を設定するにはどうすればよいですか

  2. このコードを使用する場合:

    Desc d = new Desc(); d.Descr = "新しい";

    _sess.Transaction.Begin(IsolationLevel.Serializable);

    _sess.SaveOrUpdate(d);

    var desc = _sess.CreateCriteria(typeof(Desc)).List();

    _sess.Transaction.Commit();

何も変わりません。

IsolationLevel.Serializable は何をしますか?

アップデート:

私は以下を取得する必要があります:

USE Test

BEGIN TRANSACTION

SELECT TOP 1 Id FROM [Desc] (UPDLOCK)

INSERT INTO [Desc] (Descr) VALUES ('33333')

SELECT * FROM [Desc] 

COMMIT TRANSACTION

次のNHibernateのヘルプを使用して実行するにはどうすればよいですか:

SELECT TOP 1 Id FROM [Desc] (UPDLOCK)

?

4

1 に答える 1

3

トランザクション分離レベルをスナップショットに変更します。これにより、データの読み取り時のロックが回避され、同時実行性が大幅に向上し、特に読み取り専用トランザクションでデッドロックが発生しなくなります。

デッドロックの理由は次のとおりです。挿入は互いに競合しません。新しく挿入された行をロックします。ただし、クエリは、他のトランザクションから新しく挿入された行を読み取ろうとするため、ロックアウトされます。したがって、2 つのクエリが両方とも他のトランザクションが完了するのを待っているため、デッドロックが発生します。分離レベルのスナップショットでは、クエリはコミットされていない行をまったく気にしません。ロックが解放されるのを待つ代わりに、コミットされた行のみを「参照」します。これにより、クエリのデッドロックが回避されます。

于 2013-03-28T10:46:04.113 に答える