prosource

일부 컴퓨터에서 트랜잭션 범위가 자동으로 MSDTC로 에스컬레이션됩니까?

probook 2023. 5. 8. 22:20
반응형

일부 컴퓨터에서 트랜잭션 범위가 자동으로 MSDTC로 에스컬레이션됩니까?

이 프로젝트에서는 트랜잭션 범위를 사용하여 데이터 액세스 계층이 트랜잭션에서 작업을 수행하도록 보장합니다.최종 사용자의 컴퓨터에서 MSDTC 서비스를 활성화할 필요는 없습니다.

문제는 개발자 컴퓨터의 절반에서 MSDTC를 비활성화한 상태로 실행할 수 있다는 것입니다.나머지 절반은 활성화되어 있어야 합니다. 그렇지 않으면 "MSDTC on [SERVER] is unavailable" 오류 메시지가 표시됩니다.

그것은 정말 저를 골치 아프게 하고 ADO 기반의 가정용 트랜잭션 범위와 같은 솔루션으로 되돌아갈 것을 진지하게 고려하게 합니다.NET 트랜잭션 개체입니다.우리 개발자의 절반에서 작동하는 코드(확대되지 않는 코드)가 다른 개발자의 코드에서 확대되는 것처럼 보입니다.

트랜잭션이 DTC로 에스컬레이션되는 이유가 무엇인지 추적에 대한 더 나은 답변을 기대했지만 안타깝게도 그렇지 않습니다.

여기 문제를 일으키는 코드 샘플이 있습니다. 두 번째 연결에서 문제를 확대하려고 하는 기계에서 확대하려고 합니다.열기() (예, 현재 열려 있는 다른 연결이 없습니다.)

using (TransactionScope transactionScope = new TransactionScope() {
   using (SqlConnection connection = new SqlConnection(_ConStr)) {
      using (SqlCommand command = connection.CreateCommand()) {
         // prep the command
         connection.Open();
         using (SqlDataReader reader = command.ExecuteReader()) {
            // use the reader
            connection.Close();
         }
      }
   }

   // Do other stuff here that may or may not involve enlisting 
   // in the ambient transaction

   using (SqlConnection connection = new SqlConnection(_ConStr)) {
      using (SqlCommand command = connection.CreateCommand()) {
         // prep the command
         connection.Open();  // Throws "MSDTC on [SERVER] is unavailable" on some...

         // gets here on only half of the developer machines.
      }
      connection.Close();
   }

   transactionScope.Complete();
}

우리는 이것을 알아내려고 정말로 노력했습니다.다음은 이 기능이 작동하는 기계에 대한 몇 가지 정보입니다.

  • 개발 1: Windows 7 x 64 SQL 2008
  • 개발 2: Windows 7 x86 SQL 2008
  • 개발 3: 윈도우 7 x 64 SQL 2005 SQL 2008

작동하지 않는 개발자:

  • 개발 4: 윈도우 7 x 64, SQL 2008 SQL 2005
  • 개발 5: 윈도우 비스타 x86, SQL 2005
  • 개발 6: Windows XP X86, SQL 2005
  • 내 홈 PC: Windows Vista Home Premium, x86, SQL 2005

문제를 해결하기 위해 모든 컴퓨터가 Microsoft Update에서 사용할 수 있는 모든 것으로 완전히 패치되었습니다.

업데이트 1:

  • http://social.msdn.microsoft.com/forums/en-US/windowstransactionsprogramming/thread/a5462509-8d6d-4828-aefa-a197456081d3/ 에서도 비슷한 문제를 설명합니다.2006년에!
  • http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope%28VS.80%29.aspx - 코드 샘플을 읽어보면 (실제 두 번째 SQL 서버에 대한) 중첩된 초 단위의 연결이 명확하게 표시되어 DTC로 에스컬레이션됩니다.코드에서 작업을 수행하지 않습니다. 다른 SQL 서버나 연결 문자열을 사용하지 않으며, 중첩된 보조 연결이 열려 있지 않습니다. DTC로 에스컬레이션되지 않아야 합니다.
  • http://davidhayden.com/blog/dave/archive/2005/12/09/2615.aspx (2005년부터)에서는 SQL2000에 연결할 때 항상 DTC로 에스컬레이션되는 방법에 대해 설명합니다.SQL 2005/2008을 사용하고 있습니다.
  • http://msdn.microsoft.com/en-us/library/ms229978.aspx 트랜잭션 에스컬레이션에 대한 MSDN.

해당 MSDN 트랜잭션 에스컬레이션 페이지에는 다음 조건으로 인해 트랜잭션이 DTC로 에스컬레이션된다고 나와 있습니다.

  1. 단일 단계 알림을 지원하지 않는 하나 이상의 지속적인 리소스가 트랜잭션에 등록되었습니다.
  2. 단일 단계 알림을 지원하는 두 개 이상의 내구성 있는 리소스가 트랜잭션에 등록됩니다.예를 들어 단일 연결을 등록해도 트랜잭션이 승격되지 않습니다.그러나 데이터베이스 등록을 유발하는 데이터베이스에 대한 두 번째 연결을 열 때마다 시스템이 열립니다.트랜잭션 인프라는 트랜잭션에서 두 번째로 유용한 리소스임을 감지하고 MSDTC 트랜잭션으로 에스컬레이션합니다.
  3. 트랜잭션을 다른 응용 프로그램 도메인 또는 다른 프로세스로 "마샬"하는 요청이 실행됩니다.예를 들어, 응용 프로그램 도메인 경계를 가로지르는 트랜잭션 개체의 직렬화입니다.트랜잭션 개체는 값별로 마샬링됩니다. 즉, 동일한 프로세스에서도 응용 프로그램 도메인 경계를 통과하려고 하면 트랜잭션 개체가 직렬화됩니다.트랜잭션을 매개 변수로 사용하는 원격 메서드를 호출하여 트랜잭션 개체를 전달하거나 원격 트랜잭션 서비스 구성 요소에 액세스하려고 시도할 수 있습니다.이렇게 하면 트랜잭션이 응용 프로그램 도메인에서 직렬화될 때 트랜잭션 개체가 직렬화되고 에스컬레이션이 발생합니다.배포 중이며 로컬 트랜잭션 관리자가 더 이상 적합하지 않습니다.

우리는 3위를 경험하지 않습니다.#2는 한 번에 하나의 연결만 있기 때문에 발생하지 않으며, 하나의 '유효한 리소스'에 대한 것이기도 합니다.#1이 일어날 수 있는 방법이 있습니까?단상 알림을 지원하지 않는 SQL 2005/8 구성이 있습니까?

업데이트 2:

개인적으로 모든 사용자의 SQL Server 버전을 다시 조사했습니다. "Dev 3"에는 SQL 2008이 있고 "Dev 4"에는 SQL 2005가 있습니다.그러면 다시는 동료들을 믿지 말라는 교훈을 얻을 수 있을 겁니다.;) 이러한 데이터의 변화로 인해 문제를 발견했다고 확신합니다.SQL 2008에는 SQL 2005에는 없는 엄청난 양의 기능이 포함되어 있기 때문에 SQL 2008 개발자들은 문제를 겪지 않았습니다.

또한 SQL 2005를 지원하기 때문에 지금처럼 TransactionScope를 사용할 수 없으며 TransactionScope를 사용하려면 단일 SqlConnection 개체를 전달해야 합니다.이는 SqlConnection을 쉽게 전달할 수 없는 상황에서 문제가 있는 것처럼 보입니다. 이는 글로벌 SqlConnection 인스턴스의 냄새일 뿐입니다.퓨!

업데이트 3

이 질문에 대해 분명히 말씀드리자면,

SQL 2008:

  • 단일 트랜잭션 범위 내에서 여러 연결을 허용합니다(위 샘플 코드 참조).
  • 주의 #1: 이러한 여러 SqlConnection이 중첩된 경우, 즉 두 개 이상의 SqlConnection이 동시에 열리면 트랜잭션 범위가 즉시 DTC로 에스컬레이션됩니다.
  • 주의 #2: 다른 '내구성 리소스'(즉, 다른 SQL 서버)에 대한 추가 SQL 연결이 열리면 즉시 DTC로 에스컬레이션됩니다.

SQL 2005:

  • 단일 트랜잭션 범위 내에서 여러 연결을 허용하지 않습니다.두 번째 SqlConnection이 열리면 에스컬레이션됩니다.

업데이트 4

이 질문을 더 많이 만들기 위해. 엉망인 유용하고, 좀 더 명확하게 하기 위해, 여기 SQL 2005를 단일로 DTC로 에스컬레이션할 수 있는 방법이 있습니다. SqlConnection:

using (TransactionScope transactionScope = new TransactionScope()) {
   using (SqlConnection connection = new SqlConnection(connectionString)) {
      connection.Open();
      connection.Close();
      connection.Open(); // escalates to DTC
   }
}

제가 보기엔 고장난 것 같은데요, 하지만 제가 이해할 수 있을 것 같아요.SqlConnection.Open()연결 풀에서 가져오는 중입니다.

"그런데 왜 이런 일이 생길까요?"해당 연결을 열기 전에 해당 연결에 대해 SqlTableAdapter를 사용하면 SqlTableAdapter가 연결을 열고 닫을 것입니다. 이제 다시 열 수 없으므로 트랜잭션을 효과적으로 완료할 수 있습니다.

따라서 기본적으로 SQL 2005에서 TransactionScope를 성공적으로 사용하려면 첫 번째 TransactionScope가 인스턴스화된 시점부터 더 이상 필요하지 않을 때까지 열려 있는 일종의 글로벌 연결 개체가 있어야 합니다.글로벌 연결 개체의 코드 냄새 외에도 연결을 먼저 열고 마지막으로 닫는 것은 연결을 최대한 늦게 열고 최대한 빨리 닫는 논리와 상충됩니다.

은 여러 SQL Server 2008을 할 수 .SQLConnectionTransactionScope연결이 동시에 열려 있지 않으면 여러 개의 "물리적" TCP 연결이 발생하므로 에스컬레이션이 필요합니다.

개발자 중 일부는 SQL Server 2005를 사용하고 다른 일부는 SQL Server 2008을 사용하고 있습니다.에스컬레이션 중인 항목과 그렇지 않은 항목을 올바르게 식별했습니까?

가장 명확한 설명은 SQL Server 2008을 사용하는 개발자들이 증가하고 있지 않다는 것입니다.

이 주제에 대한 제 연구 결과:

여기에 이미지 설명 입력

원하지 않는 분산 트랜잭션 에스컬레이션 방지를 참조하십시오.

저는 여전히 Oracle의 에스컬레이션 동작을 조사하고 있습니다.동일한 DB에 대한 여러 연결에 걸친 트랜잭션이 DTC로 에스컬레이션됩니까?

코드로 인해 2005년에 연결할 때 에스컬레이션이 발생합니다.

MSDN의 설명서를 확인하십시오. - http://msdn.microsoft.com/en-us/library/ms172070.aspx

SQL Server 2008에서 승격 가능한 트랜잭션

의 버전 2.0.NET Framework 및 SQL Server 2005에서 트랜잭션 범위 내의 두 번째 연결을 열면 두 연결 모두 동일한 연결 문자열을 사용하더라도 트랜잭션이 자동으로 전체 분산 트랜잭션으로 승격됩니다.이 경우 분산 트랜잭션은 불필요한 오버헤드를 추가하여 성능을 저하시킵니다.

SQL Server 2008 및 의 버전 3.5부터 시작합니다.NET Framework, 이전 트랜잭션이 종료된 후 트랜잭션에서 다른 연결이 열린 경우 로컬 트랜잭션은 더 이상 분산 트랜잭션으로 승격되지 않습니다.이미 연결 풀링을 사용하고 트랜잭션에 등록한 경우에는 코드를 변경할 필요가 없습니다.

개발 3: Windows 7 x64, SQL 2005가 성공하고 개발 4: Windows 7 x64가 실패하는 이유를 설명할 수 없습니다.당신은 그것이 반대가 아니라고 확신합니까?

왜 이 답변이 삭제되었는지는 모르겠지만 관련 정보가 있는 것 같습니다.

2010년 8월 4일 17시 42분에 에두아르도가 대답했습니다.

  1. 트랜잭션에서 자동 등록을 방지하려면 연결 문자열에 Engry=false를 설정합니다.

  2. 수동으로 연결을 트랜잭션 범위의 참가자로 등록합니다.[원본 기사가 오래됨] 또는 다음 작업을 수행합니다.MSDTC 자동 프로모션 방지 방법 [archive.is ]

중첩 연결이 문제인지 잘 모르겠습니다.SQL Server의 로컬 인스턴스를 호출하려고 하는데 DTC가 생성되지 않습니까?

    public void DoWork2()
    {
        using (TransactionScope ts2 = new TransactionScope())
        {
            using (SqlConnection conn1 = new SqlConnection("Data Source=Iftikhar-PC;Initial Catalog=LogDB;Integrated Security=SSPI;"))
            {
                SqlCommand cmd = new SqlCommand("Insert into Log values(newid(),'" + "Dowork2()" + "','Info',getDate())");
                cmd.Connection = conn1;
                cmd.Connection.Open();
                cmd.ExecuteNonQuery();

                using (SqlConnection conn2 = new SqlConnection("Data Source=Iftikhar-PC;Initial Catalog=LogDB;Integrated Security=SSPI;Connection Timeout=100"))
                {
                    cmd = new SqlCommand("Insert into Log values(newid(),'" + "Dowork2()" + "','Info',getDate())");
                    cmd.Connection = conn2;
                    cmd.Connection.Open();
                    cmd.ExecuteNonQuery();
                }
            }

            ts2.Complete();
        }
    }

내부에서 둘 이상의 연결을 사용하는 경우 트랜잭션 범위는 항상 DTC 트랜잭션으로 에스컬레이션됩니다.DTC가 비활성화된 상태에서 위의 코드가 작동할 수 있는 유일한 방법은 두 번 모두 연결 풀에서 동일한 연결을 얻는 경우입니다.

"문제는 개발자 컴퓨터의 절반에서 MSDTC를 비활성화한 상태로 실행할 수 있다는 것입니다."사용할 수 없는 것이 확실합니까 ;)

connectionString이 풀링을 false로 설정하지 않았는지 확인합니다.그러면 트랜잭션 범위의 각 새 SqlConnection이 새로 연결되고 DTC로 에스컬레이션됩니다.

언급URL : https://stackoverflow.com/questions/1690892/transactionscope-automatically-escalating-to-msdtc-on-some-machines

반응형