Transactionscopes and Distributed Transactions

828 views
Skip to first unread message

Roy Jacobs

unread,
Oct 19, 2012, 8:21:39 AM10/19/12
to nhibernate-...@googlegroups.com
Hi all,

I see quite a few bugs on JIRA relating to the same topic:

They're all about the fact that SQL errors cause a session's SqlConnection to be closed from a different thread than the thread that opened it (through the AdoNetDistributedTransacionFactory). We've been running into this issue for quite some time now as well. We store NServiceBus saga's using NHibernate and occasionally we may get a deadlock. Normally this would not be a huge problem (just retry the message), but once this deadlock occurs, we get, for a minute or 2, a log full of errors like "New request is not allowed to start because it should come with valid transaction descriptor" and "Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.".

Now, this is something we'd like to have fixed, or fix ourselves. Is anyone actively looking at this, right now? Or willing to share some suggestions/findings?

Roy

Oskar Berggren

unread,
Oct 19, 2012, 8:31:55 AM10/19/12
to nhibernate-...@googlegroups.com
I started to look at all those issues in unison a few weeks back (that's when a unified them under the TransactionScope label) and I have a few ideas plus some things that needs further thought. Currently, I think that some of those issues are "simple" bugs that should be fixed, while other issues might in fact be unsolvable with the approach that NH currently use.

Eventually I decided that I need to finish and merge the .Net 4 changes first, before I shift focus. This should be really close now.

/Oskar


2012/10/19 Roy Jacobs <roy.j...@gmail.com>

Roy Jacobs

unread,
Oct 19, 2012, 8:39:26 AM10/19/12
to nhibernate-...@googlegroups.com
Ah, okay. Good to hear! One of the workarounds I've read is to use the regular non-distributed factory because the underlying SqlConnection will enlist anyway, but that it may cause problems with second level caching. Are there alternative workarounds to consider for now?

Roy

Johannes Gustafsson

unread,
Oct 19, 2012, 9:34:27 AM10/19/12
to nhibernate-...@googlegroups.com
+1

We've had the same problems for a long time but I never considered that it could be because of a bug in NH :-).

2012/10/19 Roy Jacobs <roy.j...@gmail.com>

Johannes Gustafsson

unread,
Apr 30, 2013, 8:34:08 AM4/30/13
to nhibernate-...@googlegroups.com
I have discovered that if NH throws certain exceptions and you after that explicitly rolls back the NH transaction (like NSB does), then it will consistently corrupt the connection pool. Removing the explicit rollback makes the problem go away, at least in this specific scenario.

Example

using (create TxScope)
using (open session)
using (begin NH.Trans)

try {
session.QueryOver()...SingleOrDefault() // results return 2 rows which makes NH throw
}
catch (Exception) {
  nhtx.Rollback(); // Throws with message: ROLLBACK without corresponding BEGIN
  // Connection pool is now corrupt
}



2013/4/30 Yngve Nilsen <yngve....@gmail.com>
Exactly the same problem here when running NHibernate in NServiceBus hosted services. In our case it doesn't have to be a deadlock, just a general failure within the transaction. It seems to be related to the fact that the SQL ConnectionPool and DTC have some issues with multithreading... Would be awesome to see a fix for this in NHibernate, since I don't think the underlying MSDTC or SqlConnectionPool is going to be changed anytime soon.
--
 
---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Ramon Smits

unread,
May 1, 2013, 4:24:37 AM5/1/13
to nhibernate-...@googlegroups.com

Well, AFAIK the NH transaction is automatically rolled back in the dispose so there is no need to explicitly call Rollback on the nhibernate transaction but it should not result in e exceptions.




var session = CurrentSessionContext.Unbind(SessionFactory);

using (session)
using (session.Transaction)
{
if (!session.Transaction.IsActive)
return;

if (ex != null)
session.Transaction.Rollback();
else
session.Transaction.Commit();
}


They perform an explicit rollback as you mentioned.

Are you maybe also using NHibernate within you own message handlers or saga's?





-- Ramon

Johannes Gustafsson

unread,
May 2, 2013, 5:00:53 AM5/2/13
to nhibernate-...@googlegroups.com
Yes, it seems to only show up when using multiple NH sessions.

I managed to track it a bit further. See here: http://pastebin.com/dKyu6YN9

In the code above I use 2 NH transactions. When I get an exception from NH, I first try to rollback the first transaction. This succeeds. It seems though that NH also rolls back the second TX but it doesn't update the transaction object immediately (probably because it is done in a background thread). If, howerver, I insert a thread.sleep() after tx #1 rollback, then the IsActive property on Tx #2 will return false and the code will work as expected.

So the best workaround should be to simply remove the rollback I suppose.


2013/5/1 Ramon Smits <ramon...@gmail.com>

Joseph Lam

unread,
Aug 20, 2013, 12:52:44 PM8/20/13
to nhibernate-...@googlegroups.com
In your repro I think the two sessions (therefore two DB connections) in the same tx scope causes a promotion to a distributed transaction which follows the asynchronous two-phase commit mechanism. The commit/rollback decision is communicated back via a separate thread.

Just added my comment to the related NH-3023:
https://nhibernate.jira.com/browse/NH-3023?focusedCommentId=29652&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-29652


2013/5/1 Ramon Smits <ramon...@gmail.com>

-- Ramon




2013/4/30 Yngve Nilsen <yngve....@gmail.com>
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
 
---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
 
---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages