【问题标题】:DbDataReader causing OutOfMemoryExceptionDbDataReader 导致 OutOfMemoryException
【发布时间】:2018-02-21 22:41:45
【问题描述】:

我正在使用 DbDataReader (OracleDataReader) 类从 Oracle 数据库中读取数据。我在 Visual Studio 2010 中运行该程序,使用 64 位 Windows 10 Enterprise 笔记本电脑和 32GB RAM(20GB 免费),使用 .NET 3.5(升级到较新的 .NET 版本不是一种选择。应用程序本身是32 位应用程序(不是选择)。

代码如下所示:

//...some code to setup database connection, command, etc.
DbDataReader reader = null;
int count = 0;

try {
    reader = command.ExecuteReader();
    if(reader.HasRows) {
        while(reader.Read()) {
            count++;
        }
    }
}
finally {
    if(reader != null) { reader.Close(); }
}

堆栈跟踪:

System.OutOfMemoryException was unhandled
    Message=Exception of type 'System.OutOfMemoryException' was thrown.
    Source=Oracle.DataAccess
    StackTrace:
    at Oracle.DataAccess.Client.OracleDataReader.Dispose(Boolean disposing)
    at Oracle.DataAccess.Client.OracleDataReader.Close()
    at Test.Program.Main(String[] args)
    at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Threading.ThreadHelper.ThreadStart()

我也有很多次这个堆栈跟踪:

System.OutOfMemoryException was caught
    Message=Exception of type 'System.OutOfMemoryException' was thrown.
    Source=Oracle.DataAccess
    StackTrace:
        at Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck)
        at Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, Object src, Boolean bCheck)
        at Oracle.DataAccess.Client.OracleDataReader.Read()
        at Test.Program.Main(String[] args)

在这个测试用例中我自己没有分配任何内存,我只是增加一个整数,但我仍然用尽内存,这告诉我 DbDataReader 正在分配内存并且可能没有正确释放它(或在及时)。我试过手动进行垃圾收集,看看是否有帮助,但没有。我还研究了它崩溃的行是否包含太多数据并因此填满了剩余的内存,但这也没有加起来,因为在崩溃之前从其他行读取了更多的数据(并被丢弃) .

非常感谢任何想法/帮助,谢谢!

【问题讨论】:

  • 你不能只返回COUNT(*) 而不是单独的行,因为你无论如何都要丢弃结果吗?
  • 我通常不会丢弃行,通常我正在读取数据,但这样做时内存一直不足,因此我将代码简化为基本上您在上面看到的内容,但我仍然内存不足。
  • 为什么不用特定的OracleDataReader 而不是基类呢?如何声明和初始化命令?
  • 它使用OracleDataReader,代码是通用编写的,因为我已经开发了一个完整的API来通用工作,并且部分API处理数据库和许多数据库类型的连接。该命令是一个 OracleCommand,它的 CommandText 设置为 CommandType.Text,在这种情况下,它的 CommandText 设置为查询字符串。它还将 InitialLOBFetchSize 设置为 100000,FetchSize 设置为 200000。

标签: .net memory memory-leaks out-of-memory dbdatareader


【解决方案1】:

在对 OracleCommand 和 OracleDataReader 上的各种设置进行了一些修改后,问题原来是 OracleDataReader 上的 FetchSize 最初过高。

在执行命令后在 OracleDataReader 上设置 FetchSize 可以解决问题并允许应用程序在没有任何内存错误的情况下运行。

【讨论】:

    猜你喜欢
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多