방법은 없을 테스트하는 잠재적인 좀비 트랜잭션을 참조할 수 있는 경우 롤백?

StackOverflow https://stackoverflow.com/questions/901471

문제

는 경우에는 sql 호출에 실패한,말하는 시간 제한으로 인해 교착 상태 트랜잭션으로 설정할 수 있습이 좀비 트랜잭션-난 어느 나의 코드나 프레임 워크 코드는 rollback.이 SqlTransaction 가 null 이 아닌지만,그것을 좀비할 수 있는 오류가 발생한 경우 시도 할 Rollback().구를 찾을 수 없습니다.IsZombie 을 제공합니다.

// Make sure the transaction is not null
if (transaction != null)
{
    //TODO: Is there a way to test a transaction to see if it can be rolled back?
    transaction.Rollback();  
}
도움이 되었습니까?

해결책

.NET 2.0의 System.Transactions 네임 스페이스에서 TransactionScope 클래스를 사용해 볼 수 있습니다. 이 클래스를 사용하면 트랜잭션이 자동으로 취소되고 롤백됩니다. .NET 2.0+의 ado.net은 TransactionScope Anway이며 데이터베이스가 다음과 같은 경우에 존재하는 경우 스코프에 DBTRANSACTION을 자동으로 등록합니다.

public void DoSomething()
{
    using (TransactionScope scope = new TransactionScope(TransactionScopeOptions.Required, TimeSpan.FromSeconds(60)))
    {
        MyDac();

        scope.Complete(); // If timeout occurrs, this line is never hit, scope is disposed, which causes rollback if Complete() was not called
    }
}

public class MyDac()
{

    using (SqlConnection ...)
    {
        using (SqlCommand ...)
        {
            // Do something with ADO.NET here...it will autoenroll if a transaction scope is present
        }
    }
}

TransactionScope는 내부적으로 System.Transactions.Transaction을 만듭니다.이 경우 기본적으로 단일 서버 만 관련된 경우 SQL Server로 가벼운 트랜잭션을 허용합니다. 거래에 관련된 여러 서버 또는 분산 리소스 관리자가있는 경우 TransactionScope가 래핑 한 트랜잭션은 분산 트랜잭션으로 홍보되며 MSDTC가 조정해야하며 이는 트랜잭션 스코프 사용을 복잡하게 할 수 있습니다. 모든 트랜잭션이 가벼운 경우 TransactionScope는 DB 트랜잭션을 수동으로 관리하는 데 많은 이점을 제공 할 수 있습니다.

다른 팁

나는 당신의 용서를 간청하지만 동의하지 않는 것을 피할 수는 없습니다. 클라이언트 트랜잭션은 비즈니스 프로세스 원자 운영을 가질 수있게합니다. 모든 거래 된 운영을 DB로 옮기려면 비즈니스 로직을 항상 옮기고 있습니다. 접근 방식이지만 프로그램에 약간의 복잡한 논리를 사용할 경우 고도로 권장됩니다. /foreachs, 문자열 검사 및 기타 사소한 작업은 DB로 이동하기에 실제로 무겁습니다 (때로는 불가능). 그러나 교착 상태 힌트는 매우 유용한 것으로 보이며 클라이언트 응용 프로그램에 대한 추가 제어를 제공합니다 (제 생각에는 가장 좋은 방법입니다).

건배

내가 알고있는 오래된 질문이지만 최근 에이 문제를 다루고 있었고 SQLTransactions를 안전하게 커밋/롤백하는 데 약간의 도우미 기능을 만들었습니다. 다른 사람 이이 문제에 대한 해결책을 찾고있는 경우에 게시 할 것이라고 생각했습니다.

public void CompleteTransaction(SqlTransaction transaction, bool isRollback) {
    if (transaction == null) { return; }
    try {
        if (isRollback) { 
            transaction.Rollback(); 
        } else { 
            transaction.Commit(); 
        }
    } catch (InvalidOperationException ex) {
        // In my case, I just ignored exceptions due to zombie transactions, 
        // but you could handle it differently depending on your needs
        if (ex.TargetSite == null || ex.TargetSite.ToString() != "Void ZombieCheck()") {
            throw; // Not a zombie transaction, so re-throw the exception
        }
    }
}

좀비 거래로 인한 예외 던지기 예외 세부 사항을 검토하면서 대상이 Void ZombieCheck(), 내 솔루션은 TargetSite가 그로 설정되지 않으면 좀비 거래로 인해 오류가 아니라고 가정합니다.

을 고려할 수 있습니다를 배치하는 트랜잭션 처리 코드가 내부에의 데이터베이스를 테스트할 수 있습@오류=1205 는지 확인하려면 쿼리가 피해자의 교착 상태에서 어떤 경우 다시 시도할 수 있습니다 또는 롤백.도 클라이언트 응용 프로그램을 만들고 관리하는 트랜잭션이 조금은 위험과를 피하기 위해 더 나은 가능한 경우.

이,

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top