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

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

1 过程

执行 INSERT 并锁定 Key

2 过程

执行 INSERT 并锁定密钥

1 进程想要执行 SELECT 并进入 TIMEOUT STATE 2 进程想要执行 SELECT 并进入 TIMEOUT STATE

结果:死锁

BD: MS SQL Server 2008 R2

2个问题:

  1. 如何在事务中包含的所有表上设置 UPDATE LOCK

  2. 如果我使用此代码:

    Desc d = 新的 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

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

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

于 2013-03-28T10:46:04.113 回答