SqlBulkCopy 실행시 메모리 누수

c# sql sqlbulkcopy

문제

다음 코드에서 발생하는 잘못된 메모리 누수가 발생합니다.

 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();
                }
            }
        }
    }

이 코드 세그먼트는 수천 번 실행되므로 메모리 부족 예외가 발생하는 데 단지 1 분이 소요됩니다. Ants는 IDataReader가 가리키는 행이 GC에 의해 수집되지 않기 때문이라고보고합니다. 그러나 다음 줄을 주석으로 처리 할 때이 코드 조각에 문제가 어떻게 발생했는지 알 수 없습니다.

bulkCopy.WriteToServer(reader);

누구에게 메모리 누출을 방지하는 방법에 대한 제안이 있습니까?

미리 감사드립니다.

전화 걸기 코드 :

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

수락 된 답변

나는 내 자신의 질문에 답하는 것을 절대 싫어하지만 마침내 해결책을 찾았습니다. 실수를 저지른 것에 대해 멍청한 느낌이 들었지 만, 다른 사람들이이 질문을 우연히 만났을 때를 대비해 답변을 게시하고 싶었 기 때문에 아무도 이것에 귀중한 시간을 낭비하지 않았습니다.

메모리 누출은 제공된 코드 세그먼트가 전혀 없었습니다. 사실 누수가 아닙니다.

성능 분석을 살펴보면, BulkCopy 호출이 전체 프로그램의 병목 현상이라는 것을 알았습니다. Producer-Consumer 패턴을 삽입하기 위해 DataTables에 공급합니다.

Memory Profiler에서 코드를 실행했을 때 폐기되지 않은 DataTable 개체가 나에게 표시되었다고 생각했습니다. 이것은 실제로 삽입 대기중인 대기 테이블 이었지만 테스트 데이터를 다시 사용했기 때문에 대기중인 테이블은 이미 DB에있었습니다 (그리고 이미 삽입 된 것처럼 보입니다).

BulkCopy 라인을 주석 처리하여 병목 현상을 제거하고 DataTable을 신속하게 폐기하므로 Memory Profiler에 아무런 문제가 나타나지 않았습니다. 이것은 벌크 카피 라인이 잘못한 것처럼 보입니다.

BulkCopy 코드를 1 초 지연으로 대체했을 때 병목 현상이 충분하지 않았습니다. BulkCopy를 5 초 지연으로 교체했을 때만 소비자 제작자 대기열 크기가 제어 불능 상태에 빠지는 것을 알았습니다 .... 그래서 나는 왜 빨리 메모리가 부족하게 되었습니까?

이 질문에 시간을 할애 해 주신 모든 분들께 감사드립니다. 좀 더 흥미로운 대답을하지 못해 죄송합니다.


인기 답변

GC가 정보를 수집하려면 독자를 처분해야 할 수도 있습니다. finally 블록에서 Dispose를 호출합니다.

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


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.