Oracle.DataAccess.Client.OracleException ORA-03135:连接丢失联系

时间:2010-07-30 09:08:33

标签: c# .net oracle database-connection odp.net

我有一个.Net服务,可以在每次请求时连接到Oracle数据库。它在开始时工作正常,但在我开始得到一些请求之后:

Oracle.DataAccess.Client.OracleException ORA-03135: connection lost contact
   at Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure)
   at Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, String procedure, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src)
   at Oracle.DataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior)
   at Oracle.DataAccess.Client.OracleCommand.ExecuteReader()
   at MyApp.Services.OracleConnectionWithRetry.ExecuteReader(OracleCommand command)
   ...

知道可能是什么问题吗?我处理所有连接,结果和参数。这项服务的负担非常低。

2 个答案:

答案 0 :(得分:12)

这是因为您的代码从Oracle连接池请求连接,并且连接池返回与Oracle DB的断开连接/陈旧连接。 ODP.NET本身不会测试发送给客户端的连接的连接状态。

为了安全起见,当您执行Connection.Open()

时,要么检查connection status == Open从池中收到的连接。

OR

让ODP.NET通过在web.config中的连接字符串中设置Validate Connection = true来为您进行检查。

这两种方法都会影响性能,因为每次需要连接数据库时都会测试连接状态。

我使用的第三个选项是使用例外。首先要乐观并使用从连接池返回的whateven连接。如果你得到一个ORA - 3135然后请求一个新连接并再次像while循环一样执行你的查询。在最好的情况下,您可以将第一个连接视为有效,并且您的查询将执行。在最坏的情况下,池中的所有连接都是陈旧的,在这种情况下代码将被执行N次(其中N是连接池大小)。

答案 1 :(得分:2)

我也看到过这种情况;尝试在连接字符串中使用“Pooling = false”关闭连接池。我有一个理论认为池中的空闲连接到期,但ODP.NET没有意识到它们已经过期,然后当你的应用程序抓取一个并尝试做某事时你会得到该异常。