我可以将NHibernate的AdoNetTransactionFactory与分布式事务一起使用吗?

时间:2011-12-20 21:25:54

标签: nhibernate distributed-transactions

我正在处理与Wiber服务中的NHibernate和分布式事务相关的奇怪问题。有关详细信息,请参阅Deadlocks causing 'Server failed to resume the transaction' with NHibernate and distributed transactions

似乎解决了我的问题的一件事是使用NHibernate的AdoNetTransactionFactory,而不是AdoNetWithDistributedTransactionsFactory。

我相信AdoNetWithDistributedTransactionsFactory涉及使NHibernate的第二级缓存机制正常工作,但我们没有使用它。使用AdoNetTransactionFactory与分布式事务有什么(如果有)其他问题?

谢谢你的时间!

3 个答案:

答案 0 :(得分:1)

我注意到你从其他问题/答案中提到:

SqlConnection class is not thread-safe, and that includes closing the connection 
on a separate thread. Based on this response we have filed a 
bug report for NHibernate.

但是,来自NHibernate's documentation

11.2. Threads and connections

创建NHibernate会话时应注意以下做法:

  • 永远不要为每个数据库连接创建多个并发的ISession或ITransaction实例。

  • 每个事务为每个数据库创建多个ISession时要格外小心。 ISession本身会跟踪对加载的对象所做的更新,因此不同的ISession可能会看到过时的数据。

  • ISession不是线程安全的!永远不要在两个并发线程中访问相同的ISession。 ISession通常只是一个工作单元!

    如果您尝试使用NHibernate进行多线程连接,那么它可能无法正常工作。您是否考虑过其他ORM,例如Entity Framework

    无论您选择什么ORM,数据库连接都不是线程安全的。这是普遍的。

    “许多数据库驱动程序不是线程安全的。使用单例表示如果你有很多线程,它们将共享相同的连接。单例模式不会给你线程安全。它只允许许多线程轻松共享“全球”实例。“ - https://stackoverflow.com/a/6507820/1026459

  • 答案 1 :(得分:1)

    AdoNetTransactionFactory分布式系统事务一起使用将导致NHibernate忽略这些事务,这会产生以下后果:

    • ConnectionReleaseMode.AfterTransaction不会受到尊重。相反,NHibernate将在每个语句之后释放连接,因此将从池中重新获取下一个连接的连接。根据您的数据提供商,这可能会触发将事务升级为分布式。
    • FlushMode.Commit不会受到尊重。而是需要显式刷新。 (Auto在查询可能仍然发生之前刷新。)
    • 需要与当前系统事务隔离的作品仍将包含在其中。 (除非连接字符串Enlist属性为false。)此类工作可能包括id生成器查询,例如检索表hilo生成器的下一个高值。如果事务得到滚动支持,那么NHibernate可能会使用冲突的ID。
    • NHibernate会话将无法正确跟踪它在实体上持有的锁。考虑到自己在交易之外,它会认为它没有锁定它们。因此,它可以尝试(通过示例的用户代码请求)以低于数据库中事务已经保存在其上的锁定级别来重新锁定它们。不确定结果会是什么结果。 (充其量,在最坏的情况下被忽略......)
    • 一旦开始修改数据,二级缓存就会被禁用。 NHibernate排序"无效"在这种情况下缓存条目,并仅在事务完成时重新启用它们,并进行更新。但是因为它不会意识到交易......
    • 某些扩展(可能是Envers)可能依赖于NHibernate事务事件,并且不再按预期工作。

    答案 2 :(得分:0)

    我强烈建议升级到nhibernate 3.2(或接近它的版本)。为什么?从2.1开始,对AdoNetWithDistributedTransactionFactory进行了重大改进(读取重写)。事实上,它现在正确处理TransactionScopes / ambient-transactions等。当我们在生产中运行2.1时,我们遇到许多与分布式事务相关的问题。我们几乎不得不自己修复大量的东西并重新编译NHibernate。 3.2似乎解决了很多关于这个问题的问题。

    我没有靠近我的源,但是,如果内存没有让我失望,AdoNetTransactionFactory不会检查/处理环境事务。因此,当会话中不存在NHibernate引导事务时(通过ISession.BeginTransaction()),您将处理它们。