执行SqlBulkCopy时内存泄漏

本文关键字:泄漏 内存 SqlBulkCopy 执行 | 更新日期: 2023-09-27 17:53:13

我遇到了一个严重的内存泄漏,发生在以下代码中:

 public void BulkInsert(string tableName, IDataReader reader, String connectionString)
    {
        using (var connection = new SqlConnection(connectionString))
        {
            connection.Open();
            using (var bulkCopy = new SqlBulkCopy(connection))
            {
                bulkCopy.DestinationTableName = tableName;
                bulkCopy.BulkCopyTimeout = 900;
                try
                {
                    bulkCopy.WriteToServer(reader);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    reader.Close();
                }
            }
        }
    }

此代码段被执行数千次,因此只需要一分钟就会发生内存不足异常。Ants报告说,这是因为由IDataReader指向的行没有被GC收集。但是,当我注释掉下面一行时,没有泄漏,这就是我如何将问题隔离到这段代码。

bulkCopy.WriteToServer(reader);

有没有人建议如何防止内存泄漏?

提前谢谢你。

调用代码:

 var reader = datatable.CreateDataReader();
 BulkInsert(tablename, reader, connectionString);
 reader.Dispose();
 datatable.Dispose();

执行SqlBulkCopy时内存泄漏

我非常讨厌回答我自己的问题,但我终于找到了解决方案,虽然我觉得犯这个错误很愚蠢,但我只是想把它作为答案发布,以防其他人遇到这个问题,所以没有人浪费宝贵的时间在这上面。

内存泄漏根本不在提供的代码段中-实际上它根本不是泄漏…

查看性能分析,我发现从速度上看,BulkCopy调用是整个程序的瓶颈。我有一个生产者-消费者模式为它提供数据表以供它插入。

我认为内存分析器向我展示了在我运行代码时没有被处理的DataTable对象。这些实际上是等待插入的排队表,但是因为我重用了测试数据,所以排队表已经在DB中了(因此看起来已经插入了)。

通过注释掉BulkCopy行,我实际上消除了瓶颈,数据表被快速处理,因此内存分析器上没有显示任何问题。这使得看起来好像是Bulkcopy线路出了问题。

当我用15秒延迟替换BulkCopy代码时,这还不足以成为瓶颈。只有当我用5s延迟替换BulkCopy时,我才注意到我的消费者生产者队列大小失控了....这就是为什么我很快就耗尽了内存。

感谢所有花时间回答这个问题的人。我很抱歉没有一个更有趣的答案。

您可能需要Dispose读取器以便GC收集它。在最后一个块中尝试调用Dispose.

finally
{
    //reader.Close();
    reader.Dispose();
}