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) 이상에서 분산 트랜잭션의 가용성 그룹을 변경할 수 있습니다. 분산 트랜잭션의 가용성 그룹을 변경하려면 ALTER AVAILABILITY GROUP
스크립트에 DTC_SUPPORT = PER_DB
를 포함시킵니다. 다음 예제 스크립트에서는 분산 트랜잭션을 지원하도록 가용성 그룹을 변경합니다.
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
로 구성되면 데이터베이스가 리소스 관리자로 작동할 수 있습니다. 자세한 내용은 MS DTC 설명서를 참조하십시오.
데이터베이스 엔진의 단일 인스턴스에서 둘 이상의 데이터베이스를 사용하는 트랜잭션은 실제로 분산 트랜잭션이 됩니다. 인스턴스는 분산 트랜잭션을 내부적으로 관리하므로 사용자에게는 로컬 트랜잭션처럼 작동합니다. 데이터베이스가 DTC_SUPPORT = PER_DB
로 구성된 가용성 그룹에 있는 경우 SQL Server 2017(14.x)은 SQL Server의 단일 인스턴스 내에서도 모든 데이터베이스 간 트랜잭션을 DTC로 승격합니다.
애플리케이션에서의 분산 트랜잭션 관리 방법은 로컬 트랜잭션과 많은 부분이 동일합니다. 트랜잭션이 끝나면 애플리케이션이 트랜잭션을 커밋 또는 롤백하도록 요청합니다. 트랜잭션 관리자는 분산 커밋을 다른 방법으로 관리하여 일부 리소스 관리자는 성공적으로 커밋하고 일부는 트랜잭션을 롤백하는 네트워크 오류의 발생 가능성을 최소화해야 합니다. 이렇게 하려면 두 가지(준비 단계와 커밋 단계)에서 커밋 프로세스를 관리함으로써 달성됩니다. 이를 2단계 커밋이라고 합니다.
준비 단계
트랜잭션 관리자가 커밋 요청을 수신하면 트랜잭션과 관련된 모든 리소스 관리자에게 준비 명령을 보냅니다. 그런 다음 각 리소스 관리자는 트랜잭션을 지속적으로 만들고 트랜잭션에 대한 로그 이미지를 갖고 있는 버퍼를 디스크로 플러시하는 데 필요한 모든 작업을 수행합니다. 각 리소스 관리자가 준비 단계를 완료하면 준비 성공 또는 실패 여부를 트랜잭션 관리자에게 반환합니다.
커밋 단계
트랜잭션 관리자가 모든 리소스 관리자로부터 준비 성공 알림을 받으면 각 리소스 관리자에게 커밋 명령을 보냅니다. 그런 다음에는 리소스 관리자가 커밋을 완료할 수 있습니다. 모든 리소스 관리자가 성공적인 커밋을 보고하면 트랜잭션 관리자가 애플리케이션에 성공을 알립니다. 준비 실패를 보고한 리소스 관리자가 있으면 트랜잭션 관리자가 각 리소스 관리자에게 롤백 명령을 보내서 애플리케이션에게 커밋 실패를 알립니다.
자세한 단계
다음 목록에서는 애플리케이션이 DTC와 함께 작동하여 분산 트랜잭션을 완료하는 방법을 설명합니다.
- SQL Server 인스턴스가 DTC 트랜잭션에 참여합니다. 이는 트랜잭션에 둘 이상의 리소스 관리자가 있거나 클라이언트에서 트랜잭션을 DTC 트랜잭션으로 승격하도록 요청한 경우에 발생할 수 있습니다.
- 클라이언트는 DTC 트랜잭션 내에서 SQL Server 인스턴스의 일부 작업을 수행합니다.
- 클라이언트에서 DTC 트랜잭션에 대한 커밋 또는 중단을 발급합니다.
- 클라이언트에서 중단을 발급하면 트랜잭션이 즉시 중단됩니다.
- 클라이언트에서 커밋을 발급하면 DTC에서는 트랜잭션의 모든 리소스 관리자에 트랜잭션을 준비하도록 요청하여 2단계 커밋 프로토콜을 시작합니다.
- 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가 다르기 때문입니다. 다음과 같은 경우에 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로 참조됩니다. 데이터베이스를 복구하려면 수동으로 트랜잭션을 커밋하거나 롤백합니다.
경고
트랜잭션을 수동으로 커밋하거나 롤백하면 애플리케이션에 영향을 줄 수 있습니다. 커밋 또는 롤백 동작이 애플리케이션 요구 사항과 일치하는지 확인합니다.
다음 스크립트 중 하나만 실행합니다.
- 트랜잭션을 커밋하려면 다음 스크립트를 업데이트하고 실행합니다.
yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
를 이전 오류 메시지의 미결 트랜잭션 UOW로 바꾸고 다음을 실행합니다.
KILL 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' WITH COMMIT
- 트랜잭션을 롤백하려면 다음 스크립트를 갱신하고 실행합니다.
yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
를 이전 오류 메시지의 미결 트랜잭션 UOW로 바꾸고 다음을 실행합니다.
KILL 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' WITH ROLLBACK
트랜잭션을 커밋하거나 롤백한 후에는 ALTER DATABASE
를 사용하여 데이터베이스를 온라인으로 설정할 수 있습니다. 다음 스크립트를 업데이트하고 실행합니다. - 주의 상태 데이터베이스의 이름에 대한 데이터베이스 이름을 설정합니다.
ALTER DATABASE [DB1] SET ONLINE
미결 트랜잭션을 해결하는 방법에 대한 자세한 내용은 수동으로 트랜잭션 해결(영문)을 참조하세요.
다음 단계
Always On 가용성 그룹: 상호 운용성(SQL Server)