jon*_*n h 12 sql-server nhibernate connection-pooling distributed-transactions
将NHibernate与分布式事务一起使用时,我们遇到了问题.
请考虑以下代码段:
//
// There is already an ambient distributed transaction
//
using(var scope = new TransactionScope()) {
using(var session = _sessionFactory.OpenSession())
using(session.BeginTransaction()) {
using(var cmd = new SqlCommand(_simpleUpdateQuery, (SqlConnection)session.Connection)) {
cmd.ExecuteNonQuery();
}
session.Save(new SomeEntity());
session.Transaction.Commit();
}
scope.Complete();
}
Run Code Online (Sandbox Code Playgroud)
有时,当服务器处于极端负载时,我们将看到以下内容:
如果单独使用,应用程序最终(在几秒或几分钟后)将从此条件恢复.
为什么步骤1中没有报告死锁异常?如果我们无法解决这个问题,那么我们如何防止我们的应用程序暂时无法使用?
该问题已在以下环境中重现
我已经创建了一个测试夹具,有时会为我们重现这个问题.它可以在这里找到:http://wikiupload.com/EWJIGAECG9SQDMZ
我们最终将此缩小到一个原因.
打开会话时,如果存在环境分布式事务,NHibernate会将事件处理程序附加到Transaction.TransactionCompleted,它会在分布式事务完成时关闭会话.这似乎受到竞争条件的影响,其中连接可以在死锁错误传播之前关闭并返回到池中,从而使连接处于不可用状态.
即使服务器没有任何负载,以下代码也会偶尔为我们重现错误.如果服务器上存在极端负载,则会变得更加一致.
using(var scope = new TransactionScope()) {
//
// Force promotion to distributed transaction
//
TransactionInterop.GetTransmitterPropagationToken(Transaction.Current);
var connection = new SqlConnection(_connectionString);
connection.Open();
//
// Close the connection once the distributed transaction is
// completed.
//
Transaction.Current.TransactionCompleted +=
(sender, e) => connection.Close();
using(connection.BeginTransaction())
//
// Deadlocks but sometimes does not raise exception
//
ForceDeadlockOnConnection(connection);
scope.Complete();
}
//
// Subsequent attempts to open a connection with the same
// connection string will fail
//
Run Code Online (Sandbox Code Playgroud)
我们尚未确定解决方案,但以下事项将消除问题(可能还有其他后果):
根据Microsoft(https://connect.microsoft.com/VisualStudio/feedback/details/722659/),SqlConnection类不是线程安全的,包括在单独的线程上关闭连接.基于此回复,我们已经为NHibernate提交了一份错误报告(http://nhibernate.jira.com/browse/NH-3023).
归档时间: |
|
查看次数: |
9649 次 |
最近记录: |