7

我正在处理一个与 NHibernate 和 WCF 服务中的分布式事务相关的奇怪问题。有关更多详细信息,请参阅NHibernate 和分布式事务导致“服务器无法恢复事务”的死锁

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

我相信 AdoNetWithDistributedTransactionsFactory 与使 NHibernate 的二级缓存机制正常工作有关,但我们没有使用它。将 AdoNetTransactionFactory 与分布式事务一起使用还存在哪些(如果有)其他问题?

谢谢你的时间!

4

3 回答 3

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 的文档

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

  • 于 2012-09-24T23:52:26.190 回答
    1

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

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

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

    我附近没有源,但如果内存没有让我失望,AdoNetTransactionFactory 不会检查/处理环境事务。因此,当会话中不存在一个事务时(通过 ISession.BeginTransaction()),您可以使用 NHibernate 启动事务。

    于 2011-12-25T10:07:32.667 回答