2011-09-28 8 views
4

다음 코드를 사용하여 열린 커서 제한 문제가 발생합니다. 오라클 db의 열린 커서 제한은 약 1000으로 설정됩니다. 다음 코드는 using 문 (필자는 생각합니다)에서 모든 것을 얻었지만 커서를 유지하는 것처럼 보입니다. (참고, outRefCursor2에서 아무 것도 읽을 필요가 없습니다.)Oracle ODP.NET 커서 누출?

ODP.net을 사용하여 using 또는 다른 일부가 누락 되었습니까?
는 예외 내가 DB 커서를 모니터링하기 위해 온라인으로 볼이 조각을 사용하고 반복 596

static List<Thing> GetDetailsForItems(List<string> items) { 
    DateTime start = DateTime.UtcNow; 
    var things = new List<Thing>(); 
    var spname = "SP_GET_THING_DETAILS"; 
    var outRefCursorName1 = "p_ref_cursor1"; 
    var outRefCursorName2 = "p_ref_cursor2"; 

    // Create params 
    var pInput1 = new OracleParameter("p_input1", 
        OracleDbType.Varchar2, ParameterDirection.Input); 
    pInput1.Value = ""; 
    // Input 2 can be blank 
    var pInput2 = new OracleParameter("p_input2", 
        OracleDbType.Varchar2, ParameterDirection.Input); 
    pInput2.Value = ""; 

    var outRefCursor1 = new OracleParameter(outRefCursorName1, 
        OracleDbType.RefCursor, ParameterDirection.Output); 
    var outRefCursor2 = new OracleParameter(outRefCursorName2, 
        OracleDbType.RefCursor, ParameterDirection.Output); 

    int count = 0; 
    using (var conn = new OracleConnection(CONN_STR)) { 
    conn.Open(); 
    using (var cmd = conn.CreateCommand()) { 
     cmd.Parameters.Add(pInput1); 
     cmd.Parameters.Add(pInput2); 
     cmd.Parameters.Add(outRefCursor1); 
     cmd.Parameters.Add(outRefCursor2); 
     cmd.CommandText = spname; 
     cmd.CommandType = CommandType.StoredProcedure; 
     foreach (string value in items) { 
     count++; 
     cmd.Parameters[pInput1.ParameterName].Value = value; 
     var execVal = cmd.ExecuteNonQuery(); 
     using (var refCursor = (Types.OracleRefCursor) 
           cmd.Parameters[outRefCursorName1].Value) { 
      using (var reader = refCursor.GetDataReader()) { 
      while (reader.Read()) { 
       // read columns 
       things.Add(reader["COLUMN_A"].ToString()); 
      } 
      } // close reader 
     } // close cursor 
     } // end foreach 
    } // close command 
    } // close connection   
    int seconds = (DateTime.UtcNow - start).Seconds; 
    Console.WriteLine("Finished in {0} seconds", seconds); 
    return things; 
} 

에서 지속적으로 발생합니다. 코드를 단계별로 실행하면서 커서가 합쳐지는 것을 볼 수 있습니다. 그리고 그들은 단지 cmd.ExecuteNonQuery() 라인에서 계속 추가합니다. 나는 성명서를 사용하고 나면 한방울도 못 본다. 당신은 여전히 ​​유효한 커서를 반환하는 경우이를 압축을 풉니을 종료해야합니다 outRefCursor2를 사용하지 않는 경우에도

select sum(a.value) total_cur, avg(a.value) avg_cur, max(a.value) max_cur, 
s.username, s.machine 
from v$sesstat a, v$statname b, v$session s 
where a.statistic# = b.statistic# and s.sid=a.sid 
and b.name = 'opened cursors current' 
and machine='MY COMPUTER' 
group by s.username, s.machine 
order by 1 desc; 

답변

0

없음 지금까지 일한 적이 있었다. 그래서 필사적으로 200 회 반복마다 GC 수집을 강제 종료했습니다. 다음 코드를 사용하십시오. 이상한 무엇

if (count % 200 == 0) { 
    GC.Collect(); 
} 

는 단위 테스트에서이 메서드를 호출 할 때, 수동 GC.Collect() 어떤 커서를 해제하지 않습니다. 그러나 비즈니스 계층에서 메소드를 호출하면 실제로 작동하고 Oracle Database를 모니터링하여 열린 커서가 해제 된 것을 확인할 수 있습니다. 내가하는 GC.Collect()에 갈 않을 것

5

. ODP.net은 .Net 버전과 마찬가지로 리소스를 처리하지 않으므로 을 ODP.net 명령에 의해 반환되도록 처리해야합니다. 추가 단계로 커서를 명시 적으로 닫으려면 .Close()을 명시 적으로 호출해야합니다 (처분은이를 처리해야 함).

+0

이 정답 : 쉬운이 같은 "사용"

뭔가를 사용하는 것입니다. –

3

당신은 매개 변수를 처리해야합니다 우리는

  • 을하지 않았다 때

    • 가 그래 난 내가 내 PARAMS 처분하는 것을 선호 천연 자원 누출 (가상 작업 집합)를 표시하기 전에를 확인 연결 평생 심판 커서 (아마, 미신) 처분에 대한 연결을 사용하려면/필요로 할 때 모든 문제를 방지하기 위해

      정적 목록 GetDetailsForItems (목록 항목) { 날짜 시간 시작 = 날짜 시간 .UtcNow; var things = 새 List(); var spname = "SP_GET_THING_DETAILS"; var outRefCursorName1 = "p_ref_cursor1"; var outRefCursorName2 = "p_ref_cursor2"; 제안의

      try 
      { 
          int count = 0; 
          using (var conn = new OracleConnection(CONN_STR)) 
          try 
          { 
           conn.Open(); 
           // Create params 
           var pInput1 = new OracleParameter("p_input1", OracleDbType.Varchar2, ParameterDirection.Input); 
           pInput1.Value = ""; 
           // Input 2 can be blank 
           var pInput2 = new OracleParameter("p_input2", OracleDbType.Varchar2, ParameterDirection.Input); 
           pInput2.Value = ""; 
      
           var outRefCursor1 = new OracleParameter(outRefCursorName1, OracleDbType.RefCursor, ParameterDirection.Output); 
           var outRefCursor2 = new OracleParameter(outRefCursorName2, OracleDbType.RefCursor, ParameterDirection.Output); 
      
           using (var cmd = conn.CreateCommand()) 
           { 
            cmd.Parameters.Add(pInput1); 
            cmd.Parameters.Add(pInput2); 
            cmd.Parameters.Add(outRefCursor1); 
            cmd.Parameters.Add(outRefCursor2); 
            cmd.CommandText = spname; 
            cmd.CommandType = CommandType.StoredProcedure; 
            foreach (string value in items) 
            { 
             count++; 
             cmd.Parameters[pInput1.ParameterName].Value = value; 
             var execVal = cmd.ExecuteNonQuery(); 
             using (var refCursor = (Types.OracleRefCursor) 
                   cmd.Parameters[outRefCursorName1].Value) 
             { 
              using (var reader = refCursor.GetDataReader()) 
              { 
               while (reader.Read()) 
               { 
                // read columns 
                things.Add(reader["COLUMN_A"].ToString()); 
               } 
              } // close reader 
             } // close cursor 
            } // end foreach 
           } // close command 
          } // close connection 
          finally 
          { 
      
           pInput1.Dispose(); 
           pInput2.Dispose(); 
           outRefCursorName1.Dispose(); 
           outRefCursorName2.Dispose(); 
          } 
      } 
      int seconds = (DateTime.UtcNow - start).Seconds; 
      Console.WriteLine("Finished in {0} seconds", seconds); 
      return things; 
      

      }

  • +0

    감사합니다. 그러나 커서가 foreach 루프 내에 누적되는 것처럼 보입니다 (DB 커서 수 모니터링에서부터). 따라서 루프 외부에 배치하면 도움이되지 않지만 여전히 ORA-01000을 얻을 수 있습니다. – chris

    +0

    Shute. 나는주의를 기울이지 않았다. 나는 인플루엔자로 대답해서는 안됩니다 :) 물론, 나는 당신이 매개 변수를 처분하고 저장 프로 시저에 대한 각 호출에 대해 그들을 다시 제안했다. 버그 분석 (금년 초)을했을 때, 나는 반사경에서 ODP.Net의 코드를보고 어느 정도 도움을 받았다. 오라클 패러다임을 재사용하지 않으면 서 크거나 무시할 수있는 (내 추측 : 무시할 수있는) 성능 저하를 가져올 지 여부를 판단하기 위해 살펴볼 수 있습니다. – sehe