Reputation: 15
I have next transaction:
Desc d = new Desc();
d.Descr = "new";
_sess.Transaction.Begin();
_sess.SaveOrUpdate(d);
var desc = _sess.CreateCriteria(typeof(Desc)).List<Desc>();
_sess.Transaction.Commit();
This transaction performs next query:
BEGIN TRANSACTION
INSERT
SELECT
COMMIT TRANSACTION
When I perform this code in two processes I have deadlock, because
1 Process
Perform INSERT and lock Key
2 Process
Perform INSERT and lock key
1 Process wants to perform SELECT and passes in TIMEOUT STATE 2 Process wants to perform SELECT and passes in TIMEOUT STATE
result: deadlock
BD: MS SQL Server 2008 R2
2 questions:
How do me set UPDATE LOCK on All tables what included in transaction
If I use this code:
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();
Nothing changes.
What does IsolationLevel.Serializable do ?
UPDATE:
I need to get following:
USE Test
BEGIN TRANSACTION
SELECT TOP 1 Id FROM [Desc] (UPDLOCK)
INSERT INTO [Desc] (Descr) VALUES ('33333')
SELECT * FROM [Desc]
COMMIT TRANSACTION
How do me perform with help NHibernate following:
SELECT TOP 1 Id FROM [Desc] (UPDLOCK)
?
Upvotes: 1
Views: 3322
Reputation: 64628
I would change the transaction isolation level to snapshot. This avoids locks when reading data, allows much more concurrency and particularly no deadlocks in read-only transactions.
The reason for the deadlock is following: insert do not conflict with each other. They lock the newly inserted row. The query however is locked out, because it tries to read the newly inserted row from the other transaction. So you get two queries both waiting for the other transaction to complete, which is a deadlock. With isolation level snapshot, the query doesn't care about non committed row at all. Instead of waiting for locks to be released, it only "sees" rows that had been committed. This avoids deadlocks in queries.
Upvotes: 3