2016-10-07 3 views
2

vm에서 azure sql 데이터베이스 (v12)를 사용하고 있습니다. 나는 두 개의 서로 다른 데이터베이스 인스턴스를 가지고 있습니다 - 하나는 준비를위한 것이고 다른 하나는 생산을위한 것입니다. 나는 스테이징으로부터 데이터를 가져 와서 그것을 버튼 클릭만으로 프로덕션에 삽입하려고합니다. 이 코드는 성공적으로 '때때로'무작위로 성공할 것입니다. 그렇지 않으면 다시 오류가 발생합니다.Azure - SqlBulkCopy 제한 시간이 만료 된 예외 발생

BULK COPY 예외 유형 : {0} System.Data.SqlClient.SqlException BULK COPY 메시지 : {0} 제한 시간이 만료되었습니다. 작업이 완료되기 전에 시간 초과 기간이 경과되었거나 서버가 응답하지 않습니다. 이 오류는 라우팅 대상에 연결을 시도하는 중 발생했습니다. 원래 서버에 연결하는 동안 소요 된 기간은 - [사전 로그인] 초기화 = 1; 핸드 셰이크 = 17; [로그인] 초기화 = 0; 인증 = 0; [사후 로그인] 완료 = 0;

이 작업을 수행하는 데 사용하는 코드는 다음과 같습니다. 내가 볼 수없는 결함이있을 수 있습니다. StringBuilder를 덤프하면 SELECT 쿼리가 작동하고 DELETE 쿼리가 작동하지만 SqlBulkCopy를 사용하여 데이터를 복사하려고하면 오류가 발생하는 것을 볼 수 있습니다. 어떤 도움이라도 대단히 감사하겠습니다. 벌써 많은 행운을 겪은 MSDN 문서를 살펴 보았습니다.> 더 긴 CommandTimeouts를 추가하고 더 긴 BulkCopyTimeout을 추가하고 방화벽에서 포트를 다시 구성하십시오. 아직도 운이 없다.

자원은 내가 사용했습니다 : 당신의 SqlBulkCopy의 인스턴스를 만들 때, 당신은 연결 문자열 externalConnectionString을 전달함으로써 새로운 연결을 개방하고 https://social.msdn.microsoft.com/Forums/en-US/1467d64f-69ae-4c1f-91a2-349fc5d514ae/sqlbulkcopy-fails-with-timeout-expired-error?forum=adodotnetdataproviders

https://azure.microsoft.com/nb-no/documentation/articles/sql-database-develop-direct-route-ports-adonet-v12/

Timeout expired with SqlBulkCopy

public static object SyncData() 
{ 
    StringBuilder sb = new StringBuilder(); 
    sb.AppendLine("Internal Connection..."); 
    string internalConnectionString = GetConnectionString("ConnectionString"); 
    using (SqlConnection internalConnection = new SqlConnection(internalConnectionString)) 
    { 
     internalConnection.Open();    
     SqlCommand selectCommand = internalConnection.CreateCommand(); 
     selectCommand.CommandTimeout = 180; 
     try 
     { 
      selectCommand.CommandText = "SELECT * FROM dbo.test"; 
      SqlDataReader reader = selectCommand.ExecuteReader(); 

      sb.AppendLine("External Connection..."); 
      string externalConnectionString = GetConnectionString("ExternalConnectionString"); 
      using (SqlConnection externalConnection = new SqlConnection(externalConnectionString)) 
      { 
       externalConnection.Open();    
       SqlCommand CRUDCommand = externalConnection.CreateCommand(); 
       CRUDCommand.CommandTimeout = 180; 
       SqlTransaction transaction = externalConnection.BeginTransaction("test"); 
       CRUDCommand.Connection = externalConnection; 
       CRUDCommand.Transaction = transaction; 
       try 
       { 
        CRUDCommand.CommandText = "DELETE FROM dbo.test"; 
        sb.AppendLine("DELETE: Number of rows affected = " + CRUDCommand.ExecuteNonQuery()); 
        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(externalConnection, SqlBulkCopyOptions.KeepIdentity, transaction)) 
        { 
         try 
         { 
          bulkCopy.DestinationTableName = "dbo.test"; 
          bulkCopy.BatchSize = 100; 
          bulkCopy.BulkCopyTimeout = 180; 
          bulkCopy.WriteToServer(reader); 

          sb.AppendLine("Table data copied successfully"); 

          transaction.Commit(); 
          sb.AppendLine("Transaction committed."); 
         } 
         catch (Exception ex) 
         { 
          sb.AppendLine("BULK COPY Commit Exception Type: {0}" + ex.GetType()); 
          sb.AppendLine(" BULK COPY Message: {0}" + ex.Message); 
          try 
          { 
           transaction.Rollback(); 
          } 
          catch (Exception ex2) 
          { 
           sb.AppendLine("Rollback Exception Type: {0}" + ex2.GetType()); 
           sb.AppendLine(" Message: {0}" + ex2.Message); 
          } 
         } 
         finally 
         { 
          reader.Close(); 
         } 
        } 
       } 
       catch (Exception ex) 
       { 
        sb.AppendLine("Commit Exception Type: {0}" + ex.GetType()); 
        sb.AppendLine(" Message: {0}" + ex.Message); 

        try 
        { 
         transaction.Rollback(); 
        } 
        catch (Exception ex2) 
        { 
         sb.AppendLine("Rollback Exception Type: {0}" + ex2.GetType()); 
         sb.AppendLine(" Message: {0}" + ex2.Message); 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      sb.AppendLine("Commit Exception Type: {0}" + ex.GetType()); 
      sb.AppendLine(" Message: {0}" + ex.Message); 
     } 
    } 
    return sb.ToString(); 
} 
+0

두 서버가 동일한 가상 네트워크에 있습니까? 시간 제한을 실험 해보고 배치 크기를 늘려서 왕복 횟수가 너무 많지 않으십니까? Dapper, Reactive Extensions 및 Simple.Data를 사용하여 동일한 작업을 수행하고 있지만 비슷한 프로세스가 있습니다. 내 경우에는 최상의 결과를 얻을 때까지 설정을 가지고 놀아야 만했습니다. 또한 도움이되는 재시도 논리가 있지만은 총알이 없습니다. – jcwrequests

+0

예 두 데이터베이스가 동일한 하늘빛 서버에 있습니다. 30 분까지 시간 제한을 늘리려고했지만 그걸 30 분 동안 멈추게합니다 ... 지금 당장 복사하는 표는 단지 ​​400 행 뿐이므로 배치 크기를 변경하면 아무런 영향이 없습니다. – c22joe

+0

프로세스가 동일한 가상 네트워크에서 코드를 실행하고 있습니까? – jcwrequests

답변

1

. 이로 인해 두 테이블 모두 동일한 테이블을 수정하려는 데드락 문제가 발생할 수 있습니다.

연결 문자열 대신 기존 연결 externalConnection을 SqlBulkCopy 생성자에 전달하려고 시도 했습니까?

+0

좋은 아이디어, 나는 그것을 밖으로 시도 할 것이다. – c22joe

+0

당신이 맞아요, 내가 SqlBulkCopy를 인스턴스화 할 때 나는 같은 테이블의 이전 DELETE 쿼리로 인해 테이블을 잠갔습니다. 내가해야 할 일은 생성자를'using (SqlBulkCopy bulkCopy = new SqlBulkCopy (externalConnection, SqlBulkCopyOptions.KeepIdentity, transaction))'으로 변경하는 것 뿐이다. 고맙습니다! – c22joe