.net - Oracle.ManagedDataAccess 库中可能存在内存泄漏

标签 .net oracle memory memory-leaks oledb

我开始编写一个将数据从 oracle 数据库复制到 SQL Server 数据库的程序,并立即遇到了内存问题。我正在使用 Oracle.ManagedDataAccess 库(nuget 安装命令:“install-package Oracle.ManagedDataAccess”)。该库版本为 4.122.1.0

这是我的功能:

    private static void LoadTable(TableToLoad table)
    {
        DataTable loadBuffer = null;
        //assume source is oracle for now.  assume destination is sql server
        using (OracleConnection conn = new OracleConnection(table.SourceConnectionString))
        {
            OracleDataReader reader = OracleCommands.GetDataReader(string.Format("select * from \"{0}\".\"{1}\"", table.SourceSchema, table.SourceTable),conn);
            bool foundData = reader.Read();
            if (loadBuffer == null)
            {
                loadBuffer = InitializeBuffer(reader);
            }

            int recordsAffected;

            while (foundData==true)
            {
                object[] currentRowValues = new object[reader.FieldCount];
                int valueCount = reader.GetValues(currentRowValues);
                loadBuffer.Rows.Add(currentRowValues);
                if (loadBuffer.Rows.Count >= 15000)
                {
                    SqlCommands.RunSqlCommandWithDataTableInput(string.Format("insert into {0}.{1} select * from @loadBufferTable", table.TargetSchema, table.TargetTable), table.TargetConnectionString, out recordsAffected, loadBuffer, "loadBufferTable");

                    loadBuffer.Dispose();
                    loadBuffer = null;
                    loadBuffer = InitializeBuffer(reader);
                }
                foundData = reader.Read();
            }

            if(loadBuffer.Rows.Count>0)
            {
                SqlCommands.RunSqlCommandWithDataTableInput(string.Format("insert into {0}.{1} select * from @loadBufferTable", table.TargetSchema, table.TargetTable), table.TargetConnectionString, out recordsAffected, loadBuffer, "loadBufferTable");

                loadBuffer.Dispose();
                loadBuffer = null;
            }

            reader.Close();
            reader.Dispose();
            reader = null;

        }
    }

当我运行它时,内存消耗会猛增,几分钟后我就会出现内存不足错误。我停止了这个过程,并使用诊断工具来查看使用了这么多内存的原因。几乎所有内存都被数以万计的“OraBuf”对象占用,这些对象由 DataReader.Read 方法创建。
Visual Studio Memory Usage Tool

我尝试解除分配并重新创建我用作插入批处理缓冲区的 DataTable 对象,认为 DataTable 可能以某种方式持有对 OraBuf 对象的引用,但这并没有解决问题(我最初使用的是 DataTable.Clear( ) 方法来重置 DataTable)。

为什么会发生这种情况(我能做些什么来解决它)?

感谢您的帮助。

编辑:
我在 Oracle 中的测试表中有一个 CLOB 列。该问题似乎与读取该 CLOB 值有关,因为该问题在使用其他表时不会出现(无 OutOfMemoryException)。是否有更好的库来访问我应该使用的 Oracle?

编辑 2:
我还应该提到我正在测试的表(带有 CLOB 列的表)有大约 290 万条记录,它通常在第 500,000 行和第 1,500,000 行之间的某个位置失败(内存不足故障之前的实际最低行数约为 649,000,而最高约为 1,390,000)。

编辑 3:
我尝试将这段代码配对以帮助识别问题,其中有区别的一行是:
    int valueCount = reader.GetValues(currentRowValues);

我还尝试了一次只读取一列的版本,在这种情况下,使用索引读取值会导致问题(仅在 CLOB 列上)。这是备用版本中导致异常的行:
    newRow[columnIndex] = reader[columnIndex];

最佳答案

在批处理应用程序中读取 300 万行时,我遇到了与 CLOB 列相同的问题。当我将 InitialLobFetchSize 设置为 -1 时,似乎可以控制内存使用:

command.InitialLOBFetchSize = -1;

关于.net - Oracle.ManagedDataAccess 库中可能存在内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48455712/

相关文章:

c# - 为什么 C# 中的类型别名不能在另一个别名中使用?

.net - 大型图像调整大小库

oracle - 隐藏 Oracle XE 数据库中的表

c# - 在 C# 中的存储过程中使用全局临时表

java - String.split() 的内存问题

ruby - 为什么重复的 JSON 解析会消耗越来越多的内存?

c# - c#中继承调用构造函数的顺序

javascript - .NET 4 上的 ASP.NET 导致 IE11 抛出 _doPostBack 是未定义的 javascript 错误

sql - 如何将带有十进制值的 NUMBER 作为参数传递给 FUNCTION 或 PROCEDURE

PHP数组和内存分配