2013-06-13 2 views
0

많은 새 레코드를 ORACLE 데이터베이스에 대량 삽입 (가져 오기)하는 메커니즘을 만들고 있습니다. 스레드의Transaction.Current.DependentClone을 사용하는 동안 "duplicate transaction identifier"예외 발생

창조 :

const int ThreadCount = 4; 
using (TransactionScope transaction = new TransactionScope()) 
{ 
    List<Thread> threads = new List<Thread>(threadCount); 
    for (int i = 0; i < ThreadCount; i++) 
    { 
     Thread thread = new Thread(WorkerThread); 
     thread.Start(Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete)); 
     threads.Add(thread); 
    } 
    threads.ForEach(thread => thread.Join()); 
    transaction.Complete(); 
} 

실제 작업을 수행하는 방법이 작업하는 동안

private void WorkerThread(object transaction) 
{ 
    using (DependentTransaction dTx = (DependentTransaction)transaction) 
    using (TransactionScope ts = new TransactionScope(dTx)) 
    { 
     // The actual work, the inserts on the database, are executed here. 
    } 
} 

를, 내가 형 System.Data.OracleClient.OracleException의 예외가 여러 개의 스레드와 종속 트랜잭션을 사용하고 있습니다 메시지는 ORA-24757: duplicate transaction identifier입니다.

내가 뭘 잘못하고 있니? 종속적 인 트랜잭션을 잘못된 방식으로 구현하고 있습니까? Oracle과 호환되지 않습니까? 그렇다면 작업장이 있습니까?

답변

1
내가 u는이 예외를 얻을 수 있지만, 주변의 일이 될 수있는 이유에 대해 모르는

:

const int ThreadCount = 4; 
using (var connection = new OracleConnection(MyConnectionstring)) 
{ 
    connection.Open(); 
    using (var transaction = connection.BeginTransaction()) 
    { 
     List<Thread> threads = new List<Thread>(ThreadCount); 
     for (int i = 0; i < ThreadCount; i++) 
     { 
      Thread thread = new Thread(WorkerThread); 
      thread.Start(transaction); 
      threads.Add(thread); 
     } 
     threads.ForEach(thread => thread.Join()); 

     transaction.Commit(); 
    } 
} 

과 노동 계급이 같은 보일 것이다 : 나는 노력을 뵙죠 동안

private void WorkerThread(object transaction) 
{ 
    OracleTransaction trans = (OracleTransaction) transaction; 

    using (OracleCommand command = trans.Connection.CreateCommand()) 
    { 
     command.CommandText = "INSERT INTO mytable (x) values (1) "; 
     command.ExecuteNonQuery(); 
    } 
} 
+0

을, 정말 도움이되지 않습니다. 연결은 여러 스레드에서 공유 할 수 없기 때문에 연결은 해당 (아닌) 쿼리를 실행하는 동안 연결을 "잠글"것입니다. 단일 스레드 환경보다 더 느린 솔루션의 결과입니다 ... –

+0

나는 당신의 솔루션에 대해 좀 더 생각했습니다. '준비'부분 (가져 오기, 데이터 수집 등)이 점점 커지면 점점 더 속도가 빨라질 것입니다. 스레드 된 INSERT가 속도를 높이는 것이 아니라 '준비'부분을 여러 스레드에서 분리 할 수 ​​있다는 사실입니다. 레코드가 '준비된'(병렬) 후에는 데이터베이스에 기록 될 수 있으며, 이는 사용자의 경우 잠긴 INSERT 작업 큐가됩니다. –

관련 문제