Always On 가용성 그룹에 대한 분산 트랜잭션 만들기

적용 대상:SQL Server

SQL Server 2017(14.x)은 가용성 그룹의 데이터베이스를 포함한 모든 분산 트랜잭션을 지원합니다. 이 문서에서는 분산 트랜잭션에 대한 가용성 그룹을 만드는 방법을 설명합니다

분산 트랜잭션을 보장하기 위해서는 데이터베이스를 분산 트랜잭션 리소스 관리자로 등록하도록 가용성 그룹을 만들어야 합니다.

참고 항목

SQL Server 2016(13.x) 서비스 팩 2 이상은 가용성 그룹의 분산 트랜잭션에 대한 완전한 지원을 제공합니다. 서비스 팩 2 이전의 SQL Server 2016(13.x) 버전은 가용성 그룹의 데이터베이스가 포함된 데이터베이스 간 분산 트랜잭션(예: 동일한 SQL Server 인스턴스에서 데이터베이스를 사용하는 트랜잭션)을 지원하지 않습니다. SQL Server 2017(14.x)에는 이러한 제한이 없습니다.

SQL Server 2016(13.x)의 구성 단계는 SQL Server 2017(14.x)과 동일합니다.

분산 트랜잭션에서 클라이언트 애플리케이션은 Microsoft Distributed Transaction Coordinator(MS DTC 또는 DTC)를 통해 여러 데이터 원본 간에 트랜잭션 일관성을 보장합니다. DTC는 지원되는 Windows Server를 기반으로 하는 운영 체제에서 사용할 수 있는 서비스입니다. 분산 트랜잭션의 경우 DTC는 트랜잭션 코디네이터입니다. 일반적으로 SQL Server 인스턴스가 리소스 관리자입니다. 데이터베이스가 가용성 그룹에 있을 때 각 데이터베이스는 고유한 리소스 관리자여야 합니다.

SQL Server는 가용성 그룹이 분산 트랜잭션을 만들지 않았을 때도 가용성 그룹의 데이터베이스에 대한 분산 트랜잭션을 방지하지는 않습니다. 그러나 가용성 그룹이 분산 트랜잭션에 대해 구성되지 않으면 일부 상황에서 장애 조치가 실패할 수 있습니다. 특히 새 주 복제본 SQL Server 인스턴스는 DTC에서 트랜잭션 결과를 가져올 수 없습니다. 장애 조치 후 SQL Server 인스턴스가 DTC에서 미결 트랜잭션의 결과를 얻도록 하려면, 분산 트랜잭션에 대한 가용성 그룹을 만듭니다.

DTC는 데이터베이스가 장애 조치(failover) 클러스터의 멤버기도 한 경우를 제외하고 가용성 그룹 처리에 포함되지 않습니다. 가용성 그룹 내에서 복제본 간의 일관성은 그룹 논리에 의해 유지 관리됩니다. 보조 복제본이 지속형 스토리지에 로그 레코드를 유지했다는 것을 확인한 후에 주 복제본이 커밋을 완료하며 호출자에 대한 커밋을 확인합니다. 그런 다음에야 주 복제본이 트랜잭션 완료를 선언합니다. 비동기 모드에서는 보조 복제본의 승인을 기다리지 않고, 명시적으로 소량의 데이터는 손실될 가능성이 있습니다.

전제 조건

가용성 그룹에서 분산 트랜잭션을 지원하도록 만들기 위해서는 먼저 다음 필수 조건을 충족해야 합니다:

  • 분산 트랜잭션에 참여하는 모든 SQL Server 인스턴스는 SQL Server 2016(13.x) 이상이어야 합니다.

  • Windows Server 2012 R2 이상에서 가용성 그룹이 실행되어야 합니다. Windows Server 2012 R2의 경우에는 사용할 수 있는https://support.microsoft.com/kb/3090973 KB3090973에 업데이트를 설치해야 합니다.

분산 트랜잭션에 대한 가용성 그룹을 만듭니다

분산 트랜잭션에 대한 가용성 그룹을 구성합니다. 각 데이터베이스가 리소스 관리자로 등록할 수 있도록 가용성 그룹을 설정합니다. 이 문서에서는 각 데이터베이스가 DTC의 리소스 관리자가 될 수 있도록 가용성 그룹을 구성하는 방법을 설명합니다.

SQL Server 2016(13.x) 이상에서 분산 트랜잭션에 대한 가용성 그룹을 만들 수 있습니다. 분산 트랜잭션에 대한 가용성 그룹을 만들기 위해서는 가용성 그룹 정의에 포함시킵니다DTC_SUPPORT = PER_DB. 다음 스크립트에서는 분산 트랜잭션에 대한 가용성 그룹을 만듭니다.

CREATE AVAILABILITY GROUP MyAG
   WITH (
      DTC_SUPPORT = PER_DB  
      )
   FOR DATABASE DB1, DB2
   REPLICA ON
      'Server1' WITH (
         ENDPOINT_URL = 'TCP://SERVER1.corp.com:5022',  
         AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,  
         FAILOVER_MODE = AUTOMATIC  
         ),
      'Server2' WITH (
         ENDPOINT_URL = 'TCP://SERVER2.corp.com:5022',  
         AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,  
         FAILOVER_MODE = AUTOMATIC  
         )

참고 항목

앞의 스크립트는 가용성 그룹에 대한 간단한 예제이며 특정 프로덕션 환경을 위해 설계되지는 않았습니다.

분산 트랜잭션에 대한 가용성 그룹 변경

SQL Server 2017(14.x) 이상에서 분산 트랜잭션의 가용성 그룹을 변경할 수 있습니다. 분산 트랜잭션에 대한 가용성 그룹을 변경하려면 스크립트DTC_SUPPORT = PER_DB에 포함ALTER AVAILABILITY GROUP시킵니다. 다음 예제 스크립트에서는 분산 트랜잭션을 지원하도록 가용성 그룹을 변경합니다.

ALTER AVAILABILITY GROUP MyaAG
   SET (
      DTC_SUPPORT = PER_DB  
      );

참고

SQL Server 2016(13.x) 서비스 팩 2부터 분산 트랜잭션에 대한 가용성 그룹을 변경할 수 있습니다. 서비스 팩 2 이전의 SQL Server 2016(13.x) 버전인 경우, DTC_SUPPORT = PER_DB설정을 사용하여 가용성 그룹을 삭제하고 다시 만들어야 합니다.

분산 트랜잭션을 비활성화하려면 다음 Transact-SQL 명령을 사용합니다:

ALTER AVAILABILITY GROUP MyaAG
   SET (
      DTC_SUPPORT = NONE  
      );

분산 트랜잭션 - 기술 개념

분산 트랜잭션은 둘 이상의 데이터베이스에 걸쳐져 있습니다. 트랜잭션 관리자로서 DTC는 SQL Server 인스턴스와 다른 데이터 원본 사이의 트랜잭션을 조정합니다. SQL Server 데이터베이스 엔진의 각 인스턴스는 리소스 관리자로 작동할 수 있습니다. 가용성 그룹을 만들어질 때DTC_SUPPORT = PER_DB, 데이터베이스가 리소스 관리자로 작동할 수 있습니다. 자세한 내용은 MSIX 설명서를 참조해 주세요.

데이터베이스 엔진의 단일 인스턴스에서 둘 이상의 데이터베이스를 사용하는 트랜잭션은 실제로 분산 트랜잭션이 됩니다. 인스턴스는 내부적으로 분산 트랜잭션을 관리하기 때문에; 사용자에게 로컬 트랜잭션으로 작동됩니다. SQL Server 2017(14.x)에는 데이터베이스가 SQL Server 단일 인스턴스 내에서 만들어진 가용성 그룹에 있을 때 모든 데이터베이스 사이에서 트랜잭션을 DTC로DTC_SUPPORT = PER_DB 승격합니다.

애플리케이션에서 분산 트랜잭션의 관리 방법은 로컬 트랜잭션과 많은 부분이 동일합니다. 트랜잭션이 끝나면 애플리케이션이 트랜잭션을 커밋 또는 롤백하도록 요청합니다. 트랜잭션 관리자는 분산 커밋을 다른 방법으로 관리하여 일부 리소스 관리자는 성공적으로 커밋하고 일부는 트랜잭션을 롤백하는 네트워크 오류의 발생 가능성을 최소화해야 합니다. 이는 2단계 커밋이라고 알려진 두 단계(준비 단계와 커밋 단계)로 커밋 프로세스를 관리하여 달성됩니다.

  • 준비 단계

    트랜잭션 관리자가 커밋 요청을 수신하면 트랜잭션과 관련된 모든 리소스 관리자에게 준비 명령을 보냅니다. 그런 다음 각 리소스 관리자는 트랜잭션을 지속적으로 만들고 트랜잭션에 대한 로그 이미지를 갖고 있는 버퍼를 디스크로 플러시하는 데 필요한 모든 작업을 수행합니다. 각 리소스 관리자가 준비 단계를 완료하면 준비 성공 또는 실패 여부를 트랜잭션 관리자에게 반환됩니다.

  • 커밋 단계

    트랜잭션 관리자가 모든 리소스 관리자로부터 준비 성공 알림을 받으면 각 리소스 관리자에게 커밋 명령을 보냅니다. 그런 다음에는 리소스 관리자가 커밋을 완료할 수 있습니다. 모든 리소스 관리자가 성공적인 커밋을 보고하면 트랜잭션 관리자가 애플리케이션에 성공을 알립니다. 준비 실패를 보고한 리소스 관리자가 있는 경우 트랜잭션 관리자가 각 리소스 관리자에게 롤백 명령을 보내서 애플리케이션에 커밋 실패를 알립니다.

자세한 단계

다음 목록에서는 애플리케이션이 DTC와 함께 작동하여 분산 트랜잭션을 완료하는 방법을 설명합니다.

  1. SQL Server 인스턴스가 DTC 트랜잭션에 참여합니다. 이 문제는 트랜잭션에 둘 이상의 리소스 관리자가 있거나 클라이언트에서 트랜잭션을 DTC 트랜잭션으로 승격하도록 요청할 때 발생할 수 있습니다.
  2. 클라이언트는 DTC 트랜잭션의 SQL Server 인스턴스에서 일부 작업을 실행합니다.
  3. 클라이언트는 DTC 트랜잭션에 대한 커밋 또는 중단을 발급합니다.
    • 클라이언트에서 중단을 발급하는 경우 트랜잭션이 즉시 중단됩니다.
    • 클라이언트에서 커밋을 발급하는 경우 DTC는 트랜잭션의 모든 리소스 관리자에게 트랜잭션 준비를 요청해서 2단계 커밋 프로토콜을 시작합니다.
  4. DTC는 모든 리소스 관리자가 준비 단계를 성공적으로 승인한 후에 트랜잭션을 커밋하도록 모든 리소스 관리자에게 알립니다. 어떤 것이라도 성공적인 승인을 방해하는 경우 DTC에서 트랜잭션을 중단합니다.

분산 트랜잭션에 대한 가용성 그룹 구성의 영향

분산 트랜잭션에 참여하는 각 엔터티를 리소스 관리자라고 합니다. 리소스 관리자의 예는 다음과 같습니다:

  • SQL Server 인스턴스입니다.
  • 분산 트랜잭션에 대해 만들어진 가용성 그룹의 데이터베이스.
  • DTC 서비스 - 트랜잭션 관리자일 수도 있습니다.
  • 다른 데이터 원본.

분산 트랜잭션에 참여하기 위해 SQL Server 인스턴스가 DTC에 등록됩니다. 일반적으로 SQL Server 인스턴스는 로컬 서버에서 DTC에 등록됩니다. 각 SQL Server 인스턴스는 RMID(고유 리소스 관리자 식별자)를 사용해서 리소스 관리자를 만들고 DTC에 등록합니다. 기본 구성에서 SQL Server 인스턴스에 있는 모든 데이터베이스는 동일한 RMID를 사용합니다.

데이터베이스가 가용성 그룹에 있을 때 데이터베이스(또는 주 복제본)의 읽기-쓰기 복사본이 다른 SQL Server 인스턴스로 이동할 수 있습니다. 이러한 이동 중에 분산 트랜잭션을 지원하기 위해서는 각 데이터베이스가 별도의 리소스 관리자로 작동해야 하며 고유한 RMID가 있어야 합니다. 가용성 그룹에 DTC_SUPPORT = PER_DB가 있을 때, SQL Server에서 각 데이터베이스에 대한 리소스 관리자를 만들고 고유한 RMID를 사용하여 DTC에 등록합니다. 이 구성에서 데이터베이스는 DTC 트랜잭션에 대한 리소스 관리자입니다.

중요

DTC에서는 분산 트랜잭션당 등록이 32개로 제한됩니다. 가용성 그룹 내의 각 데이터베이스는 DTC에 별도로 등록되기 때문에 트랜잭션에 32개가 넘는 데이터베이스가 포함되어 있는 경우 SQL Server에서 33번째 데이터베이스를 등록하려고 할 때 다음 오류가 발생할 수 있습니다:

Enlist operation failed: 0x8004d101(XACT_E_TOOMANY_ENLISTMENTS). SQL Server could not register with Microsoft Distributed Transaction Coordinator (MS DTC) as a resource manager for this transaction. The transaction may have been stopped by the client or the resource manager.

SQL Server의 분산 트랜잭션에 대한 자세한 내용은 분산 트랜잭션을 참조해 주세요

해결되지 않은 트랜잭션 관리

RMID 변경 중에 존재하는 활성 트랜잭션의 결과는 장애 조치 후에 복구할 수 없습니다. 이는 등록하는 데 사용된 RMID SQL Server와 복구에 사용된 RMID SQL Server가 다르기 때문입니다. 다음과 같은 경우에 RMID 변경이 발생할 수 있습니다:

  • 가용성 그룹에 대해 변경DTC_SUPPORT합니다.
  • 가용성 그룹에서 데이터베이스를 추가 또는 제거합니다.
  • 가용성 그룹을 삭제합니다.

이러한 경우 주주 복제본에서 새 SQL Server 인스턴스로 장애 조치를 취하는 경우 인스턴스에서 DTC에 연결하여 트랜잭션 결과를 확인하려고 시도합니다. 복구가 이루어지는 동안 미결 트랜잭션에 대한 결과를 얻기 위해 데이터베이스에서 사용하고 있는 RMID가 이전에 등록되지 않았으므로 DTC에서 결과를 반환할 수 없습니다. 따라서 데이터베이스는 SUSPECT(주의 대상) 상태가 됩니다.

새로운 SQL Server 오류 로그에는 다음 예제와 같은 항목이 있습니다:

Microsoft Distributed Transaction Coordinator (MS DTC) 
failed to reenlist citing that the database RMID does 
not match the RMID [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx] 
associated with the transaction.  Please manually resolve
the transaction.
    
SQL Server detected a DTC/KTM in-doubt transaction with UOW 
{yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy}.Please resolve it 
following the guideline for Troubleshooting DTC Transactions.

앞의 예제에서는 DTC가 장애 조치 이후에 만들어진 트랜잭션의 새 주 복제본에서 데이터베이스를 다시 등록할 수 없음을 보여주고 있습니다. SQL Server 인스턴스는 분산 트랜잭션의 결과를 확인할 수 없으므로 데이터베이스를 주의 대상으로 표시합니다. 트랜잭션은 UOW(작업 단위)로 표시되고 GUID에 의해 참조됩니다. 데이터베이스를 복구하려면 트랜잭션을 수동으로 커밋하거나 롤백합니다.

경고

트랜잭션을 수동으로 커밋하거나 롤백할 때 애플리케이션에 영향을 줄 수 있습니다. 커밋 또는 롤백 작업이 애플리케이션 요구 사항과 일치하는지 확인합니다.

다음 스크립트 중 하나만 실행합니다:

  • 트랜잭션을 커밋하려면 다음 스크립트를 업데이트하고 실행합니다. - 를 이전 오류 메시지의 미결 트랜잭션 UOWyyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy로 바꾸고 다음을 실행합니다:
KILL 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' WITH COMMIT
  • 트랜잭션을 롤백하려면 다음 스크립트를 업데이트하고 실행합니다.- 를 이전 오류 메시지의 미결 트랜잭션 UOWyyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy 로 바꾸고 다음을 실행합니다:
KILL 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' WITH ROLLBACK

트랜잭션을 커밋하거나 롤백한 후에는 ALTER DATABASE를 사용하여 데이터베이스를 온라인으로 설정할 수 있습니다. 다음 스크립트를 업데이트하고 실행합니다.- 주의 상태 데이터베이스의 이름에 대한 데이터베이스 이름을 설정합니다:

ALTER DATABASE [DB1] SET ONLINE

미결 트랜잭션을 해결하는 방법에 대한 자세한 내용은 수동으로 트랜잭션 해결을 참조해 주세요.

다음 단계

분산 트랜잭션

Always On 가용성 그룹: 상호 운용성(SQL Server)

트랜잭션 - Always On 가용성 그룹 및 데이터베이스 미러링

XA 트랜잭션 지원

작동 방식: DTC 트랜잭션에 대한 세션/SPID(-2)