2

我在 .Net 4.0 中创建了一个 Windows 服务,除其他外,它需要对 Oracle 数据库做两件事。一种是运行 SELECT 查询以查看具有用户(通过电话 UI)ID 的记录是否存在,另一种是将新记录插入到表中。

一切正常,直到服务运行了一天左右 - 这里有一定程度的随机性,有时它会运行几天,大多数情况下它只是在服务重新启动后运行 24 小时。

一旦问题出现,我就开始收到 OracleExceptions。在这个问题的结尾处包含了一个完整的例外。异常表明打开到服务器的套接字要么失败,要么被“我的”机器上的软件关闭。

现在,有一些迹象表明这并不是真正的网络/数据库错误。

  1. 我有一个小型控制台实用程序,它使用完全相同的库代码从服务器读取。如果我在服务左右抛出异常的同时运行它,它可以毫无问题地使用数据库服务器验证数据。

  2. 如果我重新启动 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 会话,以查看一旦出现此问题,网络级别上实际发生了什么,但目前我真的不知道我在寻找什么,或者如果我能找到失败的连接,它会告诉我什么打开一个插座。

任何人都知道可能导致这种情况的原因,以及可以做些什么?

非常感谢您的任何意见!

4

2 回答 2

0

您应该使用“使用”块来确保及时处理资源,即使发生异常也是如此。先试试这个看看能不能解决问题:

public bool CheckIfIdExists(string paramValue)
{
    var result = false;

    using (var conn = new OracleConnection(_connectionString))
    {
      conn.Open();
      using (var cmd = new OracleCommand("SQL query", conn))
      {
        cmd.CommandType = CommandType.Text
        cmd.Parameters.Add("paramName", paramValue);

        using (var rdr = cmd.ExecuteReader())
        {
          result = rdr.HasRows;
        }
      }
    }

    return result;
}
于 2013-06-17T09:26:03.197 回答
0

我知道这篇文章很旧,但几周前我遇到了同样的问题。即使在我的代码中插入“使用”语句后,错误仍然发生。只有在我创建了一个更好的日志系统之后,我才意识到导致这个错误的异常是这样的:

ORA-01033: ORACLE 初始化或关闭正在进行中

我发现的最佳解决方案是将此异常处理为休眠 5 分钟,以便预言机可以再次重新建立连接。


public void StartProcess()
{
    while(true) {
        try {
            //Everything the service does.
        }
        catch (Exception ex)
        {
              _serviceContainer.GetInstance<IErrorLogRepository>().Log(ex: ex);
              Thread.Sleep(300 * 1000);
         }
    }
}

于 2019-07-12T14:53:47.753 回答