SqlClient의 AppContext 스위치

적용 대상: .NET Framework .NET .NET Standard

ADO.NET 다운로드

AppContext 클래스를 통해 SqlClient는 이전 동작에 의존하는 호출자를 계속 지원하면서 새 기능을 제공할 수 있습니다. 사용자는 특정 AppContext 스위치를 설정하여 동작 변경을 옵트아웃할 수 있습니다.

SqlClient는 각 스위치를 처음 사용할 때 읽고 캐시합니다. 애플리케이션 시작 시 스위치를 설정하고, 어떤 SqlClient 타입을 사용하기 전에 설정하세요. SqlClient가 값을 캐시한 후 스위치를 변경해도 효과가 없습니다.

기본적으로 MultiSubnetFailover 사용

적용 대상: .NET Framework, .NET, .NET Standard

(버전 7.0부터 사용 가능)

개별 연결 문자열을 수정하지 않고 MultiSubnetFailover=true를 전역적으로 설정하려면, 애플리케이션 시작 시 AppContext 스위치 Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault를 true로 설정하세요:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault", true);

App.Config에서 이 스위치를 사용하도록 설정할 수도 있습니다.

<runtime>
  <AppContextSwitchOverrides value="Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault=true" />
</runtime>

사용하도록 설정하면 모든 연결이 연결 문자열에 설정된 것처럼 MultiSubnetFailover=true 동작합니다. 이 스위치는 기본적으로 사용하지 않도록 설정됩니다.

비동기 읽기에 패킷 멀티플렉싱 사용

적용 대상: .NET Framework, .NET, .NET Standard

(버전 7.0부터 사용 가능)

패킷 멀티플렉싱은 큰 결과 집합, 스트리밍 시나리오 또는 대량 데이터 검색과 같은 ExecuteReaderAsync 대규모 비동기 읽기 작업의 성능을 향상시킵니다. 이 기능은 두 개의 옵트인 AppContext 스위치에 의해 제어됩니다. 두 스위치를 모두 설정하면 false 새 비동기 처리 경로가 활성화됩니다.

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseCompatibilityAsyncBehaviour", false);
AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseCompatibilityProcessSni", false);

기본적으로 두 스위치는 true모두 기존(호환 가능) 동작을 유지합니다.

소수점 잘림 동작 사용

적용 대상: .NET Framework, .NET, .NET Standard

Microsoft.Data.SqlClient 2.0부터 decimal 데이터가 SQL Server에서 하는 것처럼 기본 설정으로 반올림됩니다. 이전의 잘라내기 동작을 활성화하려면 애플리케이션 시작 시 AppContext 스위치 Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal를 true로 설정할 수 있습니다:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal", true);

Windows에서 관리형 네트워킹 사용

적용 대상: .NET; .NET Standard

(버전 2.0부터 사용 가능)

Windows에서 SqlClient는 기본적으로 SNI 네트워크 인터페이스의 네이티브 구현을 사용합니다. 관리형 SNI 구현을 사용하려면 AppContext 스위치 Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows 를 애플리케이션 시작 시로 true 설정하세요:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows", true);

이 스위치는 Windows의 .NET Core 2.1 이상 및 .NET Standard 2.0 이상 프로젝트에서 관리 네트워킹 구현을 사용하도록 드라이버의 동작을 토글하여 Microsoft.Data.SqlClient 라이브러리의 네이티브 라이브러리에 대한 모든 종속성을 제거합니다. 테스트 및 디버깅용으로만 사용됩니다.

참고

네이티브 구현과 비교했을 때 몇 가지 알려진 차이점이 있습니다. 예를 들어, 관리형 구현은 비도메인 Windows 인증을 지원하지 않습니다.

투명 네트워크 IP 해상도 비활성화

적용 대상: .NET Framework

TNIR(투명 네트워크 IP 확인)은 기존 MultiSubnetFailover 기능의 수정 버전입니다. TNIR은 호스트 이름의 첫 번째 확인된 IP가 응답하지 않고 호스트 이름과 연결된 여러 IP가 있는 경우 드라이버의 연결 시퀀스에 영향을 미칩니다. 와 TransparentNetworkIPResolution 의 MultiSubnetFailover 조합은 연결 순서를 선택합니다:

트랜스페어런트 네트워크 IP 해상도 MultiSubnetFailover 연결 시퀀스
참 참 TransparentNetworkIPResolution는 무시됩니다. 드라이버는 DNS로 해석된 IP 주소를 병렬로 시도하고, 첫 번째 응답자와 인증을 완료합니다.
참 거짓 드라이버는 DNS가 해결한 IP 주소에 대해 여러 번 연결 라운드를 실행하며, 첫 시도는 최소 500밀리초, 시도당 타임아웃은 점점 커집니다. 연결이 성공하거나 전체 Connect Timeout 타임아웃에 도달할 때까지 반복됩니다.
거짓 참 드라이버는 DNS로 해석된 IP 주소를 병렬로 시도하고, 첫 번째 응답자와 인증을 완료합니다.
거짓 거짓 드라이버는 성공하거나 Connect Timeout 도달할 때까지 각 DNS로 해석된 IP 주소를 순차적으로 시도합니다.

TransparentNetworkIPResolution기본적으로 .NET 프레임워크에서는 활성화되어 있으며, MultiSubnetFailover 기본적으로 비활성화되어 있습니다. .NET 5 및 이후 버전에서는 TransparentNetworkIPResolution는 인식되는 연결 문자열 키워드가 아니며, 이를 어떤 값으로든 설정하면 ArgumentException(KeywordNotSupported) 예외가 발생합니다. 해당 버전은 MultiSubnetFailover만 지원합니다. 이 섹션의 나머지 부분(자동 오버라이드, 다음 경고의 실패 모드, 그리고 AppContext 전환)은 .NET 프레임워크에 적용됩니다.

팁 (조언)

.NET 버전이나 대상이 Azure SQL인지 온프레미스 SQL Server인지 상관없이 모든 연결 문자열에 설정 MultiSubnetFailover=True 하세요. MultiSubnetFailover=True 첫 번째 반응형 복제본을 빠르게 찾는 병렬 연결 코드 경로를 선택합니다. .NET 프레임워크에서는 또한 TNIR의 IP 단위 순차 재시도 루프를 우회하는데, 이는 긴 연결 지연과 인증 전 핸드셰이크 타임아웃의 흔한 원인입니다.

.NET Framework에서 연결 문자열에 TransparentNetworkIPResolution이 지정되지 않은 경우, 데이터 원본이 인식된 Azure SQL 엔드포인트이거나, Authentication 키가 Microsoft Entra ID 메서드(Active Directory Password, Active Directory Integrated, Active Directory Interactive, Active Directory Service Principal, Active Directory Device Code Flow, Active Directory Managed Identity, Active Directory MSI, Active Directory Default 또는 Active Directory Workload Identity) 중 하나로 설정되어 있거나, SqlConnection.AccessToken 속성이 설정된 경우 드라이버가 TNIR을 자동으로 비활성화합니다. 드라이버가 인식하는 엔드포인트 접미사는 SqlConnection.ConnectionString의 TransparentNetworkIPResolution 항목을 참조하세요.

명시적 값은 이 자동 동작 TransparentNetworkIPResolution 을 우회하여 TNIR을 True 활성화하고 False 무조건 비활성화합니다. 자동 동작을 복원하려면 연결 문자열에서 키워드를 제거하세요. 또한 연결 문자열이 사용자 정의 CNAME이나 vanity DNS 이름을 통해 Azure SQL을 가리키는데, 접미사가 Azure SQL 엔드포인트로 인식되지 않을 때도 자동 오버라이드가 적용되지 않습니다. 자동 오버라이드는 Azure SQL을 대상으로 하며, 온프레미스 SQL Server에서는 실행되지 않으므로 기본적으로 TNIR이 켜져 있습니다.

.NET 프레임워크에서의 긴 연결 지연

.NET 프레임워크 TransparentNetworkIPResolution=True 에서는 (기본값)이 대상 DNS 이름이 여러 IP로 해석될 때 긴 연결 지연과 인증 전 핸드셰이크 타임아웃을 유발할 수 있으며, 이전 IP 중 하나가 건강하지 않거나 오래된 상태이거나 접근 불가능할 때 발생합니다. TNIR은 해결된 IP를 순차적으로 시도하며, 전체 Connect Timeout 결과에 도달할 때까지 매 라운드마다 시도당 타임아웃을 증가시킵니다. 보통 예상치 못하게 긴 연결 지연이 나타나 이런 오류로 끝납니다:

Connection Timeout Expired.  The timeout period elapsed while attempting to consume the pre-authentication handshake acknowledgement.  This could be because the pre-authentication handshake failed or the server was unable to respond back in time.

이 패턴은 여러 위상에서 나타난다:

  • Azure SQL Database, Azure SQL Managed Instance, 또는 Microsoft Fabric의 SQL 데이터베이스. Azure SQL 게이트웨이는 각 인증을 백엔드 레플리카로 라우팅합니다. 라우팅된 연결이 실패하면, TNIR은 게이트웨이로 돌아가지 않고 라우팅된 백엔드를 재시도하여 백엔드 장애 조치 시 지연을 연장합니다.
  • DNS 이름이 여러 복제본 IP 주소로 확인되는 Always On 가용성 그룹 수신기 뒤에 있는 온-프레미스 SQL Server 오래된 DNS 항목이나 건강하지 않은 복제본 IP는 TNIR이 작동하는 복제본에 도달하기 전에 순차적으로 시도됩니다.
  • 다중 서브넷 클러스터 리스너를 가진 장애 전환 클러스터 인스턴스나 대상 DNS 이름이 여러 A/AAAA 레코드를 가진 기타 구성(예: DNS 라운드로빈)입니다.

이 동작을 피하기 위해 연결 문자열에 다음과 같이 설정하세요MultiSubnetFailover=True:

MultiSubnetFailover=True

이 권고안은 모든 .NET 버전에서 작동하며 Azure SQL과 온프레미스 SQL Server 모두를 커버합니다. MultiSubnetFailover=True인 경우 드라이버는 TransparentNetworkIPResolution을 무시하고, DNS로 확인된 IP 주소들을 병렬로 시도하며, 가장 먼저 응답하는 복제본으로 인증을 완료합니다. 이름과 상관없이, MultiSubnetFailover DNS 이름이 여러 대상 IP로 해석되는 리스너에게 적용되며, 해당 IP가 서로 다른 서브넷에 있든 상관없고, DNS가 단일 IP로 해석되는 독립 실행형 서버에서는 안전합니다.

모든 연결 문자열을 편집하지 않고 프로세스 전체를 제어하려면 기본 AppContext 스위치에서 Enable MultiSubnetFailover를 사용하세요.

AppContext 스위치로 TNIR을 비활성화하세요

.NET Framework에서 TransparentNetworkIPResolution의 기본값을 true에서 false로 변경하려면, 애플리케이션 시작 시 AppContext 스위치 Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString를 true로 설정하세요. 이 스위치는 TransparentNetworkIPResolution가 연결 문자열에 없을 때만 기본값을 변경하며, 명시적으로 지정된 값은 덮어쓰지 않습니다.

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString", true);

이러한 속성 설정에 대한 자세한 내용은 SqlConnection.ConnectionString 속성 설명서를 참조하세요.

로그인 시 최소 타임아웃을 비활성화하세요

적용 대상: .NET Framework, .NET, .NET Standard

기본적으로 SqlClient는 로그인 시도에 사용할 수 있는 시간을 계산할 때 최소값을 1초로 설정합니다. 이 동작은 계산된 타임아웃이 0으로 내림되어 로그인 시도가 무한히 대기하는 것을 방지합니다.

레거시 동작을 복원하려면 애플리케이션 시작 시 AppContext 스위치 Switch.Microsoft.Data.SqlClient.UseOneSecFloorInTimeoutCalculationDuringLogin를 false로 설정하세요:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseOneSecFloorInTimeoutCalculationDuringLogin", false);

ReadAsync 차단 동작 사용 안 함

적용 대상: .NET Framework, .NET, .NET Standard

버전 3.0부터는 ReadAsync 비동기식으로 실행됩니다. 이전 버전들은 동기식으로 실행 ReadAsync 되며 .NET 프레임워크에서 호출 스레드를 차단했습니다. 이 차단 동작을 제어하려면 AppContext 스위치 Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking 를 애플리케이션 시작 시 또는 다음과 truefalse 같이 설정하세요:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking", false);

rowversion null 동작을 활성화하세요

적용 대상: .NET Framework, .NET, .NET Standard

버전 3.0부터는 행 버전이 null 값을 SqlDataReader 가질 경우 빈 값 대신 byte[]값을 반환 DBNull 합니다 빈 byte[]상태 반환이라는 레거시 동작을 활성화하려면 애플리케이션 시작 시 AppContext 스위치 Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior 를 활성화하세요.

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior", true);

안전하지 않은 TLS 경고 표시 안 함

적용 대상: .NET Framework, .NET, .NET Standard

(버전 4.0.1부터 사용 가능)

연결 문자열에서 사용할 Encrypt=false 때, TLS 버전이 1.2 이하일 경우 콘솔이 보안 경고를 출력합니다. 애플리케이션 시작 시 다음 AppContext 스위치를 활성화하여 이 경고를 억제하세요:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.SuppressInsecureTLSWarning", true);

서버 제공 장애 조치 파트너 무시

적용 대상: .NET Framework, .NET, .NET Standard

(버전 5.1.8, 6.0.4 및 6.1.3부터 사용 가능)

장애 조치 시 서버에서 제공하는 장애 조치(failover) 파트너 정보는 연결 문자열에 제공된 장애 조치(failover) 파트너 정보보다 선호됩니다. 서버에서 제공하는 장애 조치(failover) 파트너 정보를 무시하고 연결 문자열에 제공된 장애 조치(failover) 파트너 정보만 고려하려면 애플리케이션 시작 시 이 AppContext 스위치를 사용하도록 설정합니다.

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.IgnoreServerProvidedFailoverPartner", true);

연결 유휴 시간 제한 적용

적용 대상: .NET Framework, .NET, .NET Standard

버전 7.1.0부터는 SqlConnectionStringBuilder.IdleTimeout 연결 문자열 키워드와 Connection Idle Timeout 속성이 풀링된 연결에 대해 유휴 만료 검사와 백그라운드 정리를 구성합니다. 기본값은 300초입니다. 음수 값은 ArgumentException을 발생시킵니다.

스위치와 연결 문자열 설정은 각 풀 구현에 다르게 영향을 미칩니다:

  • V1 풀. 스위치가 true일 때 V1은 과거의 무작위 2~4분 정리 주기를 사용하며, Connection Idle Timeout와 관계없이 유휴 연결을 제거합니다. 스위치가 false이고 Connection Idle Timeout이 0이 아닐 때, V1은 설정된 타임아웃의 절반을 정리 주기로 사용하고 한두 번의 정리 사이클 후에 유휴 연결을 제거합니다. 스위치가 Connection Idle Timeout=0 및 false일 때, V1은 유휴 퇴거를 비활성화하지만 최소 풀 크기 유지보수는 기존의 무작위 2~4분 간격으로 계속합니다.
  • V2 풀. 스위치가 true일 때 V2는 연결별 유휴 연령 검사를 수행하지 않고, 0이 아닌 Connection Idle Timeout인 경우 백그라운드 가지치기를 활성화하고 설정합니다. 스위치가 false이고 Connection Idle Timeout가 0이 아니면 V2는 각 연결별 유휴 연령 검사를 수행하고 타임아웃부터 백그라운드 가지치기를 설정합니다. 스위치가 Connection Idle Timeout=0 및 false일 때 V2는 각 연결별 유휴 연령 검사나 백그라운드 가지치기를 수행하지 않습니다. V2는 Max Pool Size가 Min Pool Size보다 크거나 같을 때 백그라운드 가지치기를 수행하지 않습니다.
AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseLegacyIdleTimeoutBehavior", false);

구성 예시는 Limit connection Idle Time을 참조하세요.

V2 연결 풀을 활성화하세요

적용 대상: .NET Framework, .NET, .NET Standard

버전 7.1부터는 SqlClient는 대체 연결 풀 구현체(V2)를 포함하고 있습니다. V1 풀은 기본값으로 유지되며, 스위치의 기본값은 false입니다.

V2에 참여하려면 애플리케이션이 시작할 때 AppContext 스위치 Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2 를 활성화하세요:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2", true);

연결 문자열 pooling 컨트롤은 두 구현 모두에 적용됩니다. 자세한 내용은 SQL Server 연결 풀링을 참조하세요.

풀 대기와 네트워크 연결에는 단일 연결 시간 초과를 사용하세요

적용 대상: .NET Framework, .NET, .NET Standard

버전 7.1.0부터는 풀에서 연결 대기 시간을 호출자의 Connect Timeout 예산에 포함시킬 수 있어, 풀 대기와 네트워크 연결 시도가 하나의 전체 타임아웃을 공유합니다. Switch.Microsoft.Data.SqlClient.UseOverallConnectTimeoutForPoolWait을 사용 설정하면 두 연결 풀 구현 중 어느 쪽에서든 전체 타임아웃을 사용할 수 있습니다:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseOverallConnectTimeoutForPoolWait", true);

스위치의 기본값은 false입니다. 이 기본 상태는 레거시 연결 타임아웃 동작을 유지하며, 풀 작업은 완전 Connect Timeout 타임아웃을 받고 네트워크 연결 시도는 또 다른 완전한 타임아웃을 받습니다. 그 결과, Open 또는 OpenAsync는 구성된 Connect Timeout보다 더 오래 걸릴 수 있습니다.

로그인 오류 시 레거시 페일오버 전환으로 되돌리기

적용 대상: .NET Framework, .NET, .NET Standard

버전 7.1.0부터는 페일오버가 구성된 상태에서 연결할 때 로그인 단계에서 반환된 SQL 오류에 대해 SqlClient가 더 이상 페일오버 파트너로 전환하지 않습니다. 레거시 교대 동작으로 되돌리려면 애플리케이션 시작 시 AppContext 스위치 Switch.Microsoft.Data.SqlClient.UseLegacyFailoverAlternationOnLoginSqlErrors 를 활성화하세요. 스위치의 기본값은 false입니다.

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseLegacyFailoverAlternationOnLoginSqlErrors", true);

vartime 매개변수에 명시적으로 0으로 설정된 스케일을 존중하세요

적용 대상: .NET Framework, .NET, .NET Standard

기본적으로 SqlClient는 datetime2, datetimeoffset, 또는 time 매개변수에 대해 명시적으로 0으로 스케일을 설정하면 7의 척도를 보냅니다. 버전 6.0 이상에서는 명시적으로 설정된 스케일 값 0을 유지하려면 애플리케이션 시작 시 false를 Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviour로 설정하십시오. 스위치의 기본값은 true입니다.

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviour", false);