我有下一笔交易:
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个问题:
我如何在事务中包含的所有表中设置UPDATE LOCK
如果我使用此代码:
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();
没有任何改变。
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)
答案 0 :(得分:3)
我会将事务isolation level更改为快照。这样可以在读取数据时避免锁定,允许更多的并发性,特别是在只读事务中没有死锁。
死锁的原因如下:插入不会相互冲突。它们锁定新插入的行。但是查询被锁定,因为它尝试从另一个事务中读取新插入的行。所以你得到两个查询都在等待另一个事务完成,这是一个死锁。使用隔离级别快照,查询根本不关心非提交的行。它不是等待释放锁,而只是“看到”已提交的行。这可以避免查询中的死锁。