失去 Oracle 数据库连接后恢复 NHibernate
Posted
技术标签:
【中文标题】失去 Oracle 数据库连接后恢复 NHibernate【英文标题】:Restore NHibernate after lost Oracle database connection 【发布时间】:2017-03-23 01:39:21 【问题描述】:我有一个长时间运行的应用程序,它使用 NHibernate.ISessionFactory
连接到 Oracle 数据库。
有时数据库会脱机(例如,为了周末维护),但即使数据库重新联机,后续查询也会失败并出现以下异常(还显示内部异常):
NHibernate.Exceptions.GenericADOException: could not execute query
[ select .....]
>> Oracle.ManagedDataAccess.Client.OracleException: ORA-03135: Connection lost contact
>> OracleInternal.Network.NetworkException: ORA-03135: Connection lost contact
>> System.Net.Sockets.SocketException: An established connection
was aborted by the software in your host machine
重新启动应用程序会恢复功能,但我希望应用程序能够通过“重置”连接自动应对而无需重新启动。
当我遇到这个异常时,我已经用我的ISessionFactory
尝试了以下操作:
sf.EvictQueries();
sf.Close();
sf = null;
sf = <create new session factory>
但在重新创建 ISessionFactory
后看到相同的异常。我认为这是因为 NHibernate 将底层断开的连接缓存在某种连接池中?
如何说服 NHibernate 创建一个真正的新连接(或者甚至完全重置所有状态),从而允许我的应用程序自行修复连接问题而无需重新启动应用程序?
编辑:
按照 A_J 的回答,请注意我已经为每个数据库请求调用了 using (var session = _sessionFactory.OpenSession())
。
【问题讨论】:
连接池由 ADO.Net 负责,而不是 NHibernate。 【参考方案1】:我怀疑您在启动时打开ISession
(调用ISessionFactory.OpenSession()
)并在应用程序结束时关闭它。对于任何长时间运行的应用程序来说,这都是错误的方法。
您应该在较低的时间管理连接。在 Web 应用程序中,这通常是按请求处理的。在您的情况下,您应该找到应该是什么。如果您的 Windows 服务在指定时间后执行某些活动,那么 Timer_Tick 事件是个好地方。
我无法建议您的应用程序中的那个位置;你需要自己去发现。
编辑 1
查看您的编辑和评论,我认为这与 NHibernate 无关。可能是连接池正在返回一个断开/陈旧的连接到 NHibernate。
参考this 和this 接受的答案。
【讨论】:
我应该在问题中提到,我会为每个请求拨打using (var session = _sessionFactory.OpenSession())
。因此没有长时间运行的会话(据我所知)——只有一个长时间运行的 SessionFactory。谢谢 - 我会更新问题以澄清。
感谢您的链接。花了几天时间进行测试,因为我只是在一夜之间失去了数据库连接。我注意到我的连接字符串有一个Min Pool Size
,但没有Max Pool Size
。通过阅读,我想也许如果我将Max Pool Size
设置为 N,那么第二天早上可能会通过 N(自动)重试,我会回到工作状态。但是,似乎将Max Pool Size
设置为 10 实际上刚刚解决了这个问题——甚至不需要任何重试——第二天早上查询“正常工作”。我不明白这一点,所以在接下来的几天里会密切关注它......但它似乎有效。以上是关于失去 Oracle 数据库连接后恢复 NHibernate的主要内容,如果未能解决你的问题,请参考以下文章
Spring 正在失去与数据库的连接,并且无法恢复或重新连接