NHibernate在多个连接的情况下查询死锁

时间:2013-03-28 09:43:29

标签: sql-server-2008 nhibernate deadlock

我有下一笔交易:

  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

当我在两个进程中执行此代码时,我遇到了死锁,因为

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 =“new”;

    _sess.Transaction.Begin(IsolationLevel.Serializable);

    _sess.SaveOrUpdate(d);

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

    _sess.Transaction.Commit();

  3. 没有任何改变。

    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)
    

1 个答案:

答案 0 :(得分:3)

我会将事务isolation level更改为快照。这样可以在读取数据时避免锁定,允许更多的并发性,特别是在只读事务中没有死锁。

死锁的原因如下:插入不会相互冲突。它们锁定新插入的行。但是查询被锁定,因为它尝试从另一个事务中读取新插入的行。所以你得到两个查询都在等待另一个事务完成,这是一个死锁。使用隔离级别快照,查询根本不关心非提交的行。它不是等待释放锁,而只是“看到”已提交的行。这可以避免查询中的死锁。

相关问题