【发布时间】:2013-06-13 04:56:34
【问题描述】:
我在 .Net 4.0 中创建了一个 Windows 服务,其中需要对 Oracle 数据库做两件事。一种是运行 SELECT 查询以查看具有用户(通过电话 UI)ID 的记录是否存在,另一种是将新记录插入到表中。
一切正常,直到服务运行了一天左右 - 这里有一定程度的随机性,有时会运行几天,大多数情况下它只是在服务重新启动后运行 24 小时。
一旦出现问题,我就会开始收到 OracleExceptions。在这个问题的结尾处包含了一个完整的例外。异常表明打开到服务器的套接字要么失败,要么被“我的”机器上的软件关闭。
现在,有一些迹象表明这并不是真正的网络/数据库错误。
我有一个小型控制台实用程序,它使用完全相同的库代码从服务器读取。如果我在服务左右抛出异常的同时运行它,它可以毫无问题地使用数据库服务器验证数据。
如果我重新启动 Windows 服务,会立即恢复正常运行。
因此,在我的软件中使用一段时间后似乎有些东西会“厌倦”。现在,每次通话都会重新创建处理最终导致 Oracle 交互的电话呼叫的对象——希望那里不应该存在生命周期问题。同样,当这些对象需要与 Oracle 服务器通信时,会创建一个新的 OracleConnection 对象,并实例化一个新的 OracleCommand。这些和生成的 OracleDataReader 已关闭并显式处理(我什至停止使用 using() 模式以确保我真的在这样做)。这是代码的示例,在简化为几乎像孩子一样的东西以确保它做它应该做的事情之后:
public bool CheckIfIdExists(string paramValue)
{
var result = false;
var conn = new OracleConnection(_connectionString);
conn.Open();
var cmd = new OracleCommand("SQL query", conn)
{
CommandType = CommandType.Text
};
cmd.Parameters.Add("paramName", paramValue);
var rdr = cmd.ExecuteReader();
result = rdr.HasRows;
rdr.Close();
rdr.Dispose();
cmd.Dispose();
conn.Close();
conn.Dispose();
return result;
}
如您所见,我在这里没有发现任何异常 - 它们在我的代码中得到进一步处理。它们发生在尝试打开连接时。
我没有必要的 Oracle 经验来了解为什么会失败。这非常令人沮丧,因为一旦重新启动服务,问题就会消失。是否有一些连接池突然干涸,因为我没有正确处理我的资源?
这是出现问题后尝试打开与服务器的连接时遇到的异常:
Unhandled exception occurred in HandleCall: Oracle.ManagedDataAccess.Client.OracleException (0x80004005): Network Session: Unexpected packet read error ---> OracleInternal.Network.NetworkException (0x80004005): Network Session: Unexpected packet read error ---> System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at OracleInternal.Network.ReaderStream.Read(OraBuf OB)
at OracleInternal.Network.ReaderStream.Read(OraBuf OB)
at OracleInternal.TTC.OraBufReader.GetDataFromNetwork()
at OracleInternal.TTC.OraBufReader.Read(Boolean bIgnoreData)
at OracleInternal.TTC.TTCExecuteSql.ReceiveExecuteResponse(Accessor[]& defineAccessors, Accessor[] bindAccessors, Boolean bHasReturningParams, SQLMetaData& sqlMetaData, SqlStatementType statementType, Int64 noOfRowsFetchedLastTime, Int32 noOfRowsToFetch, Int32& noOfRowsFetched, Int64& queryId, Int32 longFetchSize, Int32 initialLOBFetchSize, Int64[] scnFromExecution, BindDirection[]& bindDirections, DataUnmarshaller& dataUnmarshaller)
at Oracle.ManagedDataAccess.Client.OracleException.HandleError(OracleTraceLevel level, OracleTraceTag tag, Exception ex)
at OracleInternal.TTC.TTCExecuteSql.ReceiveExecuteResponse(Accessor[]& defineAccessors, Accessor[] bindAccessors, Boolean bHasReturningParams, SQLMetaData& sqlMetaData, SqlStatementType statementType, Int64 noOfRowsFetchedLastTime, Int32 noOfRowsToFetch, Int32& noOfRowsFetched, Int64& queryId, Int32 longFetchSize, Int32 initialLOBFetchSize, Int64[] scnFromExecution, BindDirection[]& bindDirections, DataUnmarshaller& dataUnmarshaller)
at OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteReader(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, OracleDataReaderImpl& rdrImpl, Int32 longFetchSize, Int32 lobPrefetchSize, OracleDependencyImpl orclDependencyImpl, Int64[] scnForExecution, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, Boolean isEFSelectStatement)
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior)
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteReader()
[...my code beyond this point...]
我考虑过进行一次 Wireshark 会话,以查看一旦出现此问题后网络级别实际发生的情况,但目前我真的不知道我在寻找什么,或者如果我能找到它会告诉我什么打开套接字的连接失败。
有谁知道这可能是什么原因造成的,可以采取什么措施?
非常感谢您的任何意见!
【问题讨论】:
-
可能不相关,但您应该在
using语句中包含conn、cmd、rdr等,以便无论是否发生异常,它们都会被处理掉。目前,如果出现异常,它们会一直等待直到 GC 发生。 -
同意,这(参见 ShellShock 的回答)正是我在问题开始出现之前所拥有的,我不得不尝试重新格式化代码以解决它......所以虽然我同意这是正确的方法,这显然不是问题。
-
在代码中引入错误以尝试了解未知错误的原因是...一种新颖方法。假设我们在没有这些错误的情况下正确地重新编写了您发布的代码,那么在我们自己的头脑中,没有太多代码需要检查。没有什么明显的跳出来是不正确的。
-
具体来说 - 我的生产代码或多或少 100% 等于您在下面 ShellShock 的答案中看到的代码。重写您在上面看到的内容是因为我不确定 Oracle,没有使用它的经验。所以我想明确说明关闭和处置,看看它在好的情况下是否有效,并且它仍然给我带来了问题。问题的性质让我认为随着时间的推移资源会“变坏”——也许是通过处置我破坏了某些资源池的对象?我不知道,只是在这一点上做实验。 :)
标签: c# oracle windows-services