Microsoft.Data.SqlClient를 사용한 SQL Server 연결 풀링

Microsoft. Data.SqlClient 연결 풀링은 인증된 물리적 연결을 재사용합니다. SqlConnection.Open 또는 OpenAsync는 풀에서 사용 가능한 연결을 찾습니다. Close, Dispose, 또는 DisposeAsync는 이를 초기화하고 반환합니다. 이 방법은 모든 작업마다 네트워크 연결, 인증, 세션 설정을 피할 수 있습니다.

풀링은 기본적으로 활성화되어 있습니다. 다음 적용 패턴을 사용하세요:

await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(cancellationToken);

using var command = new SqlCommand(sql, connection);
await command.ExecuteNonQueryAsync(cancellationToken);

가능한 늦게 열고, 가능한 빨리 해제하며, 물리적 연결은 풀이 관리하게 하세요. 하나의 SqlConnection를 전역으로 열어 두지 마세요.

풀 키 알아보기

연결은 매칭 풀에서만 재사용할 수 있습니다. 풀 키는 목적지 서버보다 더 많은 것을 포함합니다.

Input 수영장 행동
연결 문자열 텍스트가 정확히 일치해야 합니다. 키워드 순서 차이는 효과적인 설정이 동일하더라도 별도의 풀을 만듭니다.
Windows 통합 인증 Windows 정체성은 키의 일부입니다. 같은 문자열이라도 서로 다른 식별자로 사용되면 서로 다른 풀이 생성됩니다.
SqlCredential 객체 인스턴스는 키의 일부입니다. 별도의 인스턴스는 동일한 사용자 이름과 비밀번호를 포함하더라도 별도의 풀을 생성합니다.
SqlConnection.AccessToken 액세스 토큰 값은 키의 일부입니다. 토큰 문자열을 교체하면 새로운 풀이 생성되고 기존 풀에서 기존 토큰으로 연결된 연결이 인증된 상태로 남을 수 있습니다.
SqlConnection.AccessTokenCallback 콜백이 핵심 요소의 일부입니다. 풀을 공유해야 할 연결에 대해서는 같은 콜백 인스턴스를 재사용하세요. 반환된 토큰 값은 풀 키가 아닙니다.
사용자 지정 SSPI 컨텍스트 공급자 제공자 인스턴스는 연결 구성에 참여합니다. 함께 풀링되어야 하는 연결에는 프로바이더 인스턴스 하나를 재사용하세요.
앰비언트 트랜잭션 등록된 연결은 매칭 풀 내에서 거래별 세부 분할을 사용합니다.

데이터베이스, 인증 모드, 암호화 옵션, 애플리케이션 이름, 풀링 옵션, 그리고 다른 모든 연결 문자열 값이 정확한 문자열을 통해 기여합니다.

하나의 정식 연결 문자열을 만들어 재사용하세요. Application Name, Workstation ID 또는 기타 키워드에 요청별 값을 사용하지 마세요.

풀링이 가능한 토큰 API를 선택하세요

Microsoft Entra ID 액세스 토큰의 경우 Microsoft.Data.SqlClient에서 제공하는 인증 모드 또는 안정적인 AccessTokenCallback를 사용합니다.

AccessTokenCallback는 Microsoft.Data.SqlClient 5.2에서 도입되었습니다. 드라이버는 토큰이 필요할 때 이를 호출하여 재사용 풀에 대해 새로고침된 토큰을 요청할 수 있습니다. 드라이버가 제공하는 인증 매개변수에 대한 콜백 결정성을 유지하고, 동일한 위임자 인스턴스를 재사용하세요.

코드가 AccessToken를 직접 설정할 때:

  • 토큰 문자열은 풀 키의 일부가 됩니다.
  • 애플리케이션은 토큰 만료와 새로고침을 소유합니다.
  • 풀링된 물리적 연결은 토큰을 생성하는 데 사용된 것보다 더 오래 지속될 수 있습니다.
  • 만료된 토큰을 교체한 후 해당 풀이 더 이상 안전하게 사용할 수 없다면 콜하세요 ClearPool .

모든 요청마다 새로운 콜백 람다나 자격 증명 객체를 만들지 마세요. 객체 정체성 차이는 풀을 분할할 수 있습니다.

Microsoft.Data.SqlClient 7.0은 사용자 지정 Kerberos 또는 NTLM 협상을 위해 SspiContextProvider를 추가합니다. 제공자를 요청당 상태가 아닌 애플리케이션 범위별 연결 구성으로 취급하세요.

각 풀의 크기

이 연결 문자열 옵션들은 하나의 풀을 제어합니다:

키워드 Default Effect
Pooling true 풀링을 활성화하거나 비활성화합니다.
Min Pool Size 0 풀이 생성된 후 유지할 수 있는 최소 물리적 연결 수를 설정합니다.
Max Pool Size 100 풀 내 최대 물리적 연결 수를 설정합니다.
Connect Timeout 15초 사용 가능한 연결이 없을 때 대기 시간을 Open 설정합니다.
Load Balance Timeout 0 연결 연령이 설정된 값을 초과하면 풀로 돌아올 때 그 연결을 폐기합니다. Connection Lifetime 는 별칭입니다.

풀은 수요가 증가함에 따라 연결을 생성하며 Max Pool Size에 도달할 때까지 이를 계속합니다. 모든 연결이 사용 중이면 이후의 연결 열기 요청은 연결을 다시 사용할 수 있을 때까지 기다립니다. 대기 시간이 Connect Timeout를 초과하면 열기에 실패합니다.

확인하기 전에 Max Pool Size 올리지 마세요:

  • 모든 연결과 리더는 각 경로마다 배치됩니다.
  • 명령과 거래는 신속하게 완료됩니다.
  • 쿼리 작업량이 막히거나 포화 상태가 아닙니다.
  • 데이터베이스 연결 한도는 모든 애플리케이션 인스턴스의 모든 풀에 곱할 수 있습니다 Max Pool Size .

Min Pool Size 값이 양수이면 유휴 상태 동안 연결을 열린 상태로 유지합니다. 측정 결과가 따뜻한 연결을 정당화할 때만 사용하세요. 보통 스케일링 투 제로, 서버리스 자동 일시정지, 버스터 가능한 클라우드 설계에 맞서 작동합니다.

기본 Load Balance Timeout=0 설정에서는 정기 정리가 보통 약 4분에서 8분 후에 Min Pool Size를 초과하는 미사용 연결을 제거하거나, 서버 연결이 끊어진 것을 감지하면 풀이 해당 연결을 제거합니다. 그 구간을 각 연결별 유휴 보장이 아니라 구현 동작으로 간주하세요. 풀은 매번 체크아웃 전에 검증 쿼리를 보내지 않는데, 왕복 방문 때문에 풀링 혜택이 많이 사라지기 때문입니다.

인증 차단 기간 처리

인증 타임아웃이나 기타 인증 실패 후에는 풀이 차단 기간에 들어갈 수 있습니다. 이 기간 동안 해당하는 open 시도는 다른 인증 시도를 하지 않고 원래 예외를 다시 발생시킵니다.

첫 번째 차단 시간은 5초입니다. 또 한 번 실패하면 주기가 1분으로 두 배가 됩니다.

Pool Blocking Period 이 동작을 제어합니다:

Value 작동 방식
Auto 일반 SQL Server 엔드포인트에 대한 차단을 활성화하고, 인식된 Azure SQL 엔드포인트 접미사에 대해서는 차단을 비활성화합니다. 배니티 DNS 이름은 Azure 동작을 받지 못할 수도 있습니다.
AlwaysBlock 모든 엔드포인트에 블로킹 기간을 활성화합니다.
NeverBlock 차단 기간을 비활성화합니다.

애플리케이션의 측정된 재시도 설계가 다른 선택을 요구하지 않는 한 유지 Auto 하세요. 차단 기간을 비활성화하면 자격 증명, 방화벽, 장애 문제가 인증 폭풍으로 전환될 수 있습니다.

차단 기간은 설정 가능한 재시도 논리와는 별개입니다. 차단 기간 동안 동일한 풀을 여는 재시도 공급자는 캐시된 예외를 받습니다.

연결 수명 및 삭제 관리

치명적인 오류(예: 장애 전환)를 인식하면 풀은 자동으로 해당 풀을 삭제합니다. 풀은 유휴 연결을 닫고, 대여된 연결이 반환되면 이를 폐기합니다.

알려진 구성 또는 자격 증명 경계에 대해 클리어링 API를 사용하세요:

  • ClearPool 하나의 SqlConnection 구성에 연결된 풀을 지웁니다.
  • ClearAllPools는 프로세스 또는 애플리케이션 도메인의 모든 Microsoft.Data.SqlClient 풀을 지웁니다.

수영장은 정리된 수영장에서 유휴 연결을 닫습니다. 풀에서 현재 사용 중인 연결을 표시해 두었다가 반환되면 폐기합니다.

풀을 정리하면 이후 열기 작업에서 물리적 로그인이 수행됩니다. 정기적인 유지보수, 일반적인 오류 처리기, 또는 연결 폐기의 대체품으로 사용하지 마세요.

Load Balance Timeout 연령에 따른 점진적인 이직률을 제공합니다. 배포나 클러스터 서비스가 시간이 지나면서 오래된 물리적 연결이 사라져야 할 때 사용하세요. 선택한 값이 과도한 하드 연결을 일으키지 않는지 확인하세요.

트랜잭션에 대한 이해

기본값인 Enlist=true을 사용하면 System.Transactions.Transaction.Current 내부에서 열린 연결은 자동으로 해당 트랜잭션에 참여합니다.

트랜잭션에 참여 중인 연결이 닫히면, 풀은 해당 연결을 트랜잭션별 하위 풀에 넣습니다. 같은 거래로 나중에 개설된 경우 재사용할 수 있습니다. 물리적 연결은 트랜잭션이 완료될 때까지 일반 풀로 반환되지 않습니다.

따라서 장기간 지속되거나 방치된 앰비언트 트랜잭션은 다음과 같은 문제를 초래할 수 있습니다:

  • 물리적 연결을 공용 풀에서 제외하세요.
  • 논리 연결이 종료된 후 풀 용량을 소비하세요.
  • 서버 잠금과 트랜잭션 상태를 유지하세요.

거래를 묶고, 명시적으로 완료하며, 정지 연결을 모니터링하세요. 연결이 주변 트랜잭션 외부에 유지되어야 하는 경우에만 Enlist=false를 설정하세요.

풀 단편화 방지

풀 단편화는 재사용 가능한 몇 개의 풀 대신 많은 작은 풀을 만듭니다. 주요 원인은 다음과 같습니다.

  • 연결 문자열 키워드 순서 또는 별칭 차이
  • 고객, 사용자, 요청 또는 데이터베이스마다 연결 문자열 하나.
  • 여러 Windows 신원에 통합 인증이 가능합니다.
  • 각 요청마다 새 SqlCredential, 액세스 토큰 콜백 또는 SSPI 제공자 인스턴스.
  • 매번 새로고침할 때마다 바뀌는 직접 접근 토큰.
  • 카디널리티가 높은 애플리케이션 이름 또는 워크스테이션 ID

연결 문자열을 SqlConnectionStringBuilder 정규화하고 연결 생성을 중앙집중화하세요.

애플리케이션이 의도적으로 많은 데이터베이스나 아이덴티티에 연결된다면, 그 결과 풀 수를 용량 계획에 포함시켜야 합니다. 신뢰할 수 없는 데이터베이스 이름으로 풀을 하나로 합치기 위해 USE을(를) 실행하지 마세요. 데이터베이스 격리, 권한, 세션 상태, 풀 리셋 동작은 명시적으로 유지되어야 합니다.

애플리케이션 역할과 세션 상태 고려

풀은 물리적 연결을 다른 논리 연결에 할당하기 전에 재사용 가능한 SQL Server 세션 상태를 초기화합니다. 애플리케이션 코드는 여전히 해당 작업 단위 내에서 필요한 세션 상태를 설정해야 합니다.

SQL Server 애플리케이션 역할로 sp_setapprole 활성화된 경우 일반 풀링에서는 안전하게 재설정할 수 없습니다. 데이터베이스 사용자, 포함된 사용자, 역할, 행 수준 보안 또는 기타 권한 설계를 선호합니다. 애플리케이션 역할이 불가피하다면, 문서화된 쿠키 기반 역전 패턴을 사용하거나 테스트 후 해당 고립된 경로에 대한 풀링을 비활성화하세요.

리더를 폐기하고, 트랜잭션을 종료하거나 롤백하며, 연결이 종료될 때 명령어를 계속 실행하지 마세요. 임시 테이블이나 다른 세션 상태가 논리적 연결을 통해 살아남는 것에 의존하지 마세요.

클라우드 호스팅 풀링 패턴 사용

Azure App Service, Azure Functions, 컨테이너, Kubernetes 및 기타 수평 확장되는 호스트의 경우:

  • 모든 인스턴스, 프로세스, 풀 키, 복제본에서 가능한 데이터베이스 연결을 계산하세요.
  • 연결 객체에서 토큰 문자열을 순환시키는 대신 관리 신원이나 안정적인 액세스 토큰 콜백을 사용하세요.
  • 측정된 콜드 스타트 요구 사항이 세션 유지를 정당화하는 경우가 아니라면 Min Pool Size=0를 그대로 유지하세요.
  • 새 인스턴스는 빈 풀에서 시작할 것으로 예상하세요.
  • 같은 워크로드를 담당하는 인스턴스 간에 연결 문자열을 동일하게 유지하세요.
  • 장애 조치나 스케일아웃 시 동기화된 로그인 폭주를 방지할 수 있도록 연결 시도와 재시도 횟수를 제한하세요.
  • Azure SQL 및 기타 지원되는 다중 주소 TCP 엔드포인트에 대해 MultiSubnetFailover=true를 설정합니다.

연결 풀은 애플리케이션 프로세스에 국한되어 있습니다. 애플리케이션 인스턴스, 컨테이너, 호스트 간에 공유되지 않습니다.

풀 행동 진단

SqlClient 진단 카운터를 사용하여 다음을 관찰하세요:

  • 하드 커넥트와 디스커넥트는 물리적 서버 연결을 나타냅니다.
  • 소프트 연결 및 연결 해제는 풀 체크아웃 및 반환을 의미합니다.
  • 활성 및 무료 통합 연결.
  • 활발한 수영장 그룹과 수영장.
  • 정지 연결.
  • 애플리케이션 코드가 논리 연결을 해제하지 않아 회수된 연결

클라이언트 카운터를 SQL Server 세션, 대기, 차단, 자원 제한과 연관시킵니다. 풀 타임아웃은 연결 누출, 느린 쿼리, 차단된 트랜잭션, 과도한 동시성, 풀 단편화, 데이터베이스 용량 제한을 의미할 수 있습니다.

목표 풀러 추적을 위해 이벤트 소스 트레이싱 을 사용하세요. 추적은 장황합니다. 이 기능을 활성화하여 경계 진단 창을 설정하고, 캡처된 연결 메타데이터를 보호하세요.

프로덕션 체크리스트

  • 풀링을 계속 활성화하세요.
  • 워크로드와 데이터베이스마다 하나의 표준 연결 문자열을 재사용하세요.
  • 모든 경로에서 연결, 명령어, 리더, 트랜잭션을 폐기하세요.
  • 자격 증명, 토큰 콜백, SSPI 제공자 인스턴스를 재사용하세요.
  • 유한한 연결과 명령 타임아웃을 설정하세요.
  • 모든 애플리케이션 인스턴스에 걸쳐 총 연결 예산을 세우세요.
  • 강제 연결, 풀 개수, 사용 가능한 연결, 정체 상태 및 시간 초과를 모니터링하세요.
  • 공급자가 감지할 수 없는 자격 증명, 토큰, 구성 경계가 있거나, 진단 결과 오래된 연결이 확인될 때만 풀을 삭제합니다.
  • 운영 전에 스케일아웃, 장애 조치, 자격 증명 갱신 동작을 로드 테스트하세요.