我有一个.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)
...
知道可能是什么问题吗?我处理所有连接,结果和参数。这项服务的负担非常低。
答案 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没有意识到它们已经过期,然后当你的应用程序抓取一个并尝试做某事时你会得到该异常。