2011-09-06 3 views
25

매우 간단한 질문입니다. 과 SqlBulkCopy을 함께 사용할 수 있습니까? 설명서 Transaction and Bulk Copy Operations에는 (적어도 .NET 4.0 이상에서는) 아무 것도 언급되어 있지 않으며 테스트 결과 자동으로 TransactionScope으로 등록되지 않았 음을 나타냅니다.SqlBulkCopy와 함께 System.Transactions.TransactionScope를 사용할 수 있습니까?

+0

에 잠금 시간을 최소화 할 수 있습니다 상황 http://stackoverflow.com/q/2884863/463478에 도움이 될 수 TransactionScope에 대한 몇 가지 답변입니다 –

답변

3

대량로드 (내 지식)에서 트랜잭션을 정의하는 유일한 방법은 배치 크기를 지정하는 것입니다.

대량로드의 이점은 대량 업데이트 잠금 (멀티 스레드 읽기 및 멀티 스레드 쓰기)을 얻는 것입니다. bcp, 대량 삽입, (탭 잠금), 삽입 (열) openrowset (대량)의 열 선택 또는 sqlbulkcopy를 사용하여 ssis 데이터 흐름 작업을 사용할 때이 값을 얻습니다. 로드 시간과 트랜잭션 로그 크기를 최소화하려고 할 때 편리합니다 (최소한으로 기록 된 요구 사항을 충족해야만 수백만 행을 절약 할 수 있습니다).

언제든지 데이터를로드하면 트랜잭션 로그에 병목 현상이 발생합니다. 시간이 핵심이라면 얼마나 많이 기록되는지를 최소화하는 것이 중요합니다.

일단 batchsize가 충족되면 (커밋하도록 지정한 행 수) 트랜잭션이 커밋되고 다시 시작됩니다. 배치 크기를 0으로 지정하면 트랜잭션이 전체 파일을 포함하고 데이터 문제가 발생할 경우 롤백합니다.

+0

불행합니다. 단일 행 커밋 및 일괄 행을 * 여러 * 테이블에 추가 한 다음 다른 테이블에서 단일 행 업데이트를 수행 한 다음 성공하거나 모두 성공해야합니다. 하나의'TransactionScope'에서 커밋과 대량로드 및 최종 업데이트를 래핑하는 것이 쉽기를 바랬습니다. 나는 다른 접근법을 취해야 할 것이다. 자세한 대답 주셔서 감사합니다, 많이 주셔서 감사합니다. – jason

4

모든 SqlBulkCopy 가져 오기를 수행하려면 모든 일괄 처리 (및 선택적으로 다른 데이터베이스 문의) 전체에 걸쳐 트랜잭션을 사용해야합니다. 다음 단계에서는 SqlBulkCopy를 사용하여 트랜잭션을 사용하는 프로세스에 대해 설명합니다.

  1. 대상 데이터베이스 서버에 대한 SqlConnection을 만듭니다.
  2. 연결을 엽니 다.
  3. SqlTransaction 개체를 만듭니다.
  4. SqlTransaction 개체 을 생성자로 전달하여 SqlBulkCopy 개체를 만듭니다.
  5. 가져 오기 - WriteToServer에 대한 호출 - 시도 ... 시도 블록 내에서 수행하십시오. 작업이 완료되면 트랜잭션을 커밋하십시오. 실패하면 롤백하십시오.

Using Transactions with SqlBulkCopy

+0

우리는 두 개의 데이터베이스가 관련되어 있습니까? –

+1

이 답변은 물어 본 TransactionScope에 대한 설명이 아닙니다. – usr

24

SqlBulkCopy은 결코 거래에 입대하지 않습니다. SqlCommand도 그렇게하지 않습니다. 일반적인 오해. 입대는 SqlConnection.Open이 호출 될 때 수행됩니다. 그 후, 그 연결에서 실행되는 모든 것은 암시 적으로 트랜잭션의 일부입니다. 사실 더 이상 명시 적 트랜잭션을 전달할 수 없습니다.

SqlBulkCopySystem.Transactions.Transaction에 넣으려면 TransactionScope을 사용하여 연결을 설정할 때 트랜잭션을 설정해야합니다.

아주 쉽게 할 수 있습니다 :

using (var tran = new TransactionScope(...)) 
using (var conn = new SqlConnection(connStr)) 
{ 
    conn.Open(); //This enlists. 

    using (var sqlBulkCopy = new SqlBulkCopy(conn)) { 
    sqlBulkCopy.WriteToServer(...); 
    } 

    tran.Complete(); //Commit. 
} 

이 코드는 당신이 필요로하는 모두이다. 가능한 실수 :

  1. 트랜잭션을 일찍 열어야합니다.
  2. SqlBulkCopySqlTransaction 매개 변수를 사용하지 마십시오. null을 전달하십시오.
  3. SqlBulkCopyOptions.UseInternalTransaction을 사용하지 마십시오.
  4. 실제로 처리하고 싶지 않으면 예외 처리를 추가하지 마십시오. 커밋이 없으면 롤백이 자동으로 수행됩니다.
  5. 코드 정리 및 결정적 정리에 using 문을 사용하십시오. 이 객체들을 수동으로 닫거나 처리하지 않아야합니다. 이것은 중복 될 것입니다.

원하는 배치 크기를 사용할 수 있으며 모든 배치가 트랜잭션의 일부가됩니다. 따라서 일괄 처리에는 제한된 값이 있습니다 (특히 트랜잭션 로그를 일찍자를 수 없음). 먼저 배치를 시도하지 마십시오.

-1

또 다른 방법은 실생활 여기


use SqlBulkCopy and copy data to temporary table use delete output construction to move data into production table

관련 문제