【发布时间】: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