이 드라이버는 go-mssqldb Azure SQL Database, Azure SQL Managed Instance, Microsoft Fabric의 SQL 데이터베이스 연결을 지원합니다. 이 글은 온프레미스 SQL Server와 다른 Azure 고유 설정, 인증, 연결 제한 및 문제 해결에 대해 다룹니다.
Azure SQL Database에 연결하기
Azure SQL Database는 기본적으로 암호화된 연결이 필요합니다.
encrypt=true 및 TrustServerCertificate=false를 명시적으로 지정하여 연결이 TLS를 사용하고 서버 인증서를 검증하도록 합니다:
db, err := sql.Open("sqlserver",
"sqlserver://<user>:<password>@<server>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false")
if err != nil {
panic(err)
}
메모
를 누락encrypt하면 드라이버가 자동으로 Azure 전용 TLS 설정을 추가하지 않습니다. Azure SQL 연결 문자열에서 encrypt=true&TrustServerCertificate=false를 유지하세요.
비밀번호 없는 인증 사용(권장)
Microsoft Entra ID 인증은 연결 문자열에서 비밀번호를 제거합니다.
ActiveDirectoryDefault 환경별로 가장 적합한 자격 증명을 자동으로 선택하여 개발에 편리함을 제공합니다:
import (
"database/sql"
"log"
_ "github.com/microsoft/go-mssqldb/azuread"
)
func main() {
db, err := sql.Open("azuresql",
"sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
log.Fatal(err)
}
defer db.Close()
}
Important
ActiveDirectoryDefault 개발에는 편리하지만, 여러 자격증명 소스를 탐색하기 때문에 연결 지연이 증가할 수 있습니다. 프로덕션 서비스의 경우 ActiveDirectoryManagedIdentity 또는 ActiveDirectoryServicePrincipal와 같은 명시적인 방법을 사용하는 것이 좋습니다.
ActiveDirectoryDefault가 자격 증명을 해결하는 방법
ActiveDirectoryDefault 다음 자격 증명 소스를 순서대로 시도하고 성공한 첫 번째 출처를 사용합니다:
| Order | 자격 증명 출처 | 일반적인 환경 |
|---|---|---|
| 1 | 환경 변수 (AZURE_CLIENT_ID, AZURE_TENANT_ID, ) AZURE_CLIENT_SECRET |
CI/CD 파이프라인, Docker 컨테이너 |
| 2 | 워크로드 정체성 | Azure Workload Identity를 사용하는 Kubernetes 파드 |
| 3 | 관리형 아이덴티티 | Azure VMs, App Service, Container Apps, Azure Functions |
| 4 | Azure CLI(az login) |
지역 개발 |
| 5 | Azure Developer CLI (azd auth login) |
지역 개발 |
이 자격 증명 체인은 개발 중에 ActiveDirectoryDefault를 편리하게 해 주지만, 순차적으로 확인하는 과정 때문에 새로 연결할 때마다 지연이 발생합니다. 운영 환경에서는 드라이버가 불필요한 검사를 건너뛰도록 정확한 인증 방법(예: ActiveDirectoryManagedIdentity)을 지정하세요.
프로덕션용 관리 아이덴티티 (권장)
Azure에서 호스팅되는 애플리케이션(App Service, Container Apps, Azure Functions, 또는 Azure VMs)은 명시적인 fedauth 값이 있는 관리 식별자를 사용해야 합니다. 이 방법은 자격증명 체인 오버헤드를 피하고 환경 변수나 CLI 상태에 대한 의존성을 제거합니다.
시스템 할당 관리 ID:
sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&encrypt=true&TrustServerCertificate=false
사용자 지정 관리 신원 (클라이언트 ID 지정):
sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&user id=<client-id>&encrypt=true&TrustServerCertificate=false
데이터베이스에서 신원 접근 권한을 부여합니다
Azure 리소스에서 관리 신원을 설정한 후, 포함된 데이터베이스 사용자를 생성합니다:
CREATE USER [my-app-identity] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [my-app-identity];
ALTER ROLE db_datawriter ADD MEMBER [my-app-identity];
시스템 할당 신원의 경우, Azure 리소스 이름을 사용하세요. 사용자 지정 신원의 경우, 신원 이름을 사용하세요.
자동화를 위한 서비스 주체
CI/CD 파이프라인 또는 서비스 간 인증의 경우:
sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryServicePrincipal&user id=<client-id>&password=<client-secret>&encrypt=true&TrustServerCertificate=false
모든 자격 증명 유형에 대해서는 Microsoft Entra ID 인증을 참조하세요.
Azure 방화벽을 구성하세요
Azure SQL Database는 서버 수준 방화벽을 사용합니다. 클라이언트의 공인 IP 주소를 허용하거나 사설 엔드포인트를 사용해야 합니다.
오류: 서버를 열 수 없습니다
이 오류 메시지는 Azure 방화벽이 클라이언트 IP 주소를 차단하고 있음을 나타냅니다:
mssql: login error: Cannot open server '<server>' requested by the login.
Client with IP address '<client-ip>' is not allowed to access the server.
솔루션:
- Azure 포털에 방화벽 규칙을 추가하세요: SQL 서버>네트워킹>,방화벽 규칙 추가.
- 애플리케이션이 Azure에서 실행된다면 Azure 서비스 및 리소스가 이 서버에 접근할 수 있도록 허용하세요.
- 프라이빗 연결은 프 라이빗 엔드포인트를 설정하세요.
오류: 연결 시간 초과
만약 연결이 명확한 오류 없이 타임아웃된다면, 방화벽이 조용히 연결을 차단하고 있을 가능성이 큽니다. 먼저 방화벽 규칙을 확인하세요.
서비스 계층별 연결 제한
Azure SQL Database는 서비스 계층에 따라 각 데이터베이스마다 연결 제한을 강제합니다. 제한을 초과하면 새로운 연결에서 인증 실패가 발생합니다. 전체 제한 테이블은 DTU 단일 데이터베이스 자원 제한 과 vCore 단일 데이터베이스 자원 제한을 참조하세요.
MaxOpenConns를 내 티어에 맞게 설정하세요
항상 Azure SQL 계층의 연결 한도 이하로 설정 MaxOpenConns 하세요:
// Example for S2 tier (60 max workers).
// Leave headroom for Azure management connections and other clients.
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(5 * time.Minute)
팁 (조언)
여러 애플리케이션이 동일한 데이터베이스를 공유한다면, 연결 한도를 모든 애플리케이션에 나누어 나누세요. 예를 들어, 세 개의 서비스가 S2 데이터베이스(최대 60명의 워커)를 공유할 경우, 서비스당 15-20개의 연결을 할당합니다.
Azure SQL 제한 처리
Azure SQL Database는 데이터베이스가 자원 제한(CPU, IO, 메모리, 세션 수)에 가까워질 때 연결과 쿼리를 제한할 수 있습니다. 스로틀링은 특정 오류 번호 형태로 나타납니다.
일반적인 스로틀링 오류
| 오류 번호 | 메시지 패턴 | 원인 |
|---|---|---|
| 10928 | Resource ID: %d. The %s limit for the database is %d and has been reached. |
세션 또는 워커 한도에 도달했습니다. |
| 10929 | Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d. |
리소스 거버너 스로틀링. |
| 40501 | The service is currently busy. |
일반적인 스로틀링. 다시 시도하십시오. |
| 40544 | The database has reached its size quota. |
데이터베이스 크기 제한에 도달했습니다. 재시도하기 전에 용량이나 여유 공간을 늘리세요. |
| 40549 | Session is terminated because you have a long-running transaction. |
거래 기간을 초과했습니다. |
| 40550 | Session is terminated because of too many locks. |
과도한 자물쇠 획득. |
| 40551 | Session is terminated because of excessive tempdb usage. |
과도한 tempdb 사용. |
| 40552 | Session is terminated because of excessive transaction log usage. |
거래 기록 공간이 초과됨. |
| 40553 | Session is terminated because of excessive memory usage. |
과도한 메모리 소비. |
| 40613 | Database '%.*ls' on server '%.*ls' is not currently available. |
데이터베이스가 이동되거나 재구성되고 있습니다. |
| 49918 | Cannot process request. Not enough resources to process request. |
리소스 소모. |
| 49919 | Cannot process create or update request. |
동시에 생성/업데이트 작업이 너무 많아요. |
| 49920 | Cannot process request. Too many operations in progress. |
동시 운영 한도에 도달했습니다. |
제한된 요청 재시도
앞서 언급한 표의 대부분 Azure SQL 속도 제한 및 가용성 오류는 일시적이며 지수 백오프로 재시도해야 합니다. 오류는 40544 일시적이지 않습니다. 즉, 데이터베이스가 할당량을 초과했기 때문에, 데이터베이스를 확장하거나 데이터를 삭제하기 전까지는 작업이 성공하지 못한다는 뜻입니다.
완전한 재시도 구현에 대해서는 오류 처리 및 재시도 패턴을 참조하세요.
import (
"errors"
mssql "github.com/microsoft/go-mssqldb"
)
func isAzureThrottling(err error) bool {
var mssqlErr mssql.Error
if !errors.As(err, &mssqlErr) {
return false
}
switch mssqlErr.Number {
case 10928, 10929, 40501, 40549, 40550, 40551, 40552, 40553,
40613, 49918, 49919, 49920:
return true
}
return false
}
연결 복원력
Azure SQL Database 有時會為更新、장애 조치, 負載分散等伺服器重新配置。 이러한 이벤트는 기존 연결을 끊으며, 이는 driver: bad connection 오류로 나타납니다. 풀을 자동으로 복구하도록 설정하세요:
db.SetConnMaxLifetime(5 * time.Minute) // Rotate connections so stale ones are replaced.
db.SetConnMaxIdleTime(2 * time.Minute) // Recycle before Azure gateway drops idle connections (30 min).
db.SetMaxIdleConns(10) // Keep warm connections for quick recovery.
메모
Azure SQL 게이트웨이는 약 30분 동안 유휴 상태인 연결을 닫습니다. 유휴 상태 이후 첫 번째 쿼리에서 driver: bad connection 오류가 발생하지 않도록 ConnMaxIdleTime을 이 임계값보다 훨씬 낮게 설정하세요. 트랜잭션이 아닌 호출의 경우, database/sql가 새 연결에서 자동으로 재시도합니다. 트랜잭션 호출의 경우, 코드가 오류를 포착하고 전체 트랜잭션을 다시 시도해야 합니다.
장애 전환 후 재연결
트랜잭션 외부에서는 드라이버가 연결을 사용할 수 없는 상태로 표시하는 경우, database/sql는 문제가 있는 연결에서 시작된 호출을 투명하게 다시 시도할 수 있습니다. 이 동작은 속도 제한, 장애 조치 또는 기타 재시도 가능한 SQL 오류에 대한 완전한 일시적 장애 재시도 정책이 아닙니다. 데이터베이스 호출을 재시도 함수로 랩하여 다음 상황을 처리하세요:
var count int
err := RetryFunc(ctx, DefaultRetryConfig, func(ctx context.Context) error {
return db.QueryRowContext(ctx, "SELECT COUNT(*) FROM HumanResources.Employee").Scan(&count)
})
Azure SQL Managed Instance(애저 SQL 매니지드 인스턴스)
Azure SQL Managed Instance는 온프레미스 SQL Server와 동일한 드라이버 기능을 지원하지만 몇 가지 차이점이 있습니다:
| 특징 | Azure SQL 데이터베이스 | Azure SQL Managed Instance(애저 SQL 매니지드 인스턴스) |
|---|---|---|
| SQL Server 에이전트 | 사용할 수 없음 | 사용할 수 있음 |
| 데이터베이스 간 쿼리 | 사용할 수 없음 | 사용할 수 있음 |
| 연결된 서버 | 사용할 수 없음 | 사용할 수 있음 |
| 명명된 파이프 | 사용할 수 없음 | 사용 불가 (TCP 전용) |
| 공유 메모리 | 사용할 수 없음 | 사용 불가 (TCP 전용) |
| Windows 인증(SSPI) | 사용할 수 없음 | 관리형 VNet 내에서 이용 가능 |
Managed Instance에 연결:
sqlserver://<user>:<password>@<instance>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false
Microsoft Fabric의 SQL 데이터베이스
Important
Fabric의 SQL 데이터베이스는 Microsoft Entra ID 인증이 필요합니다. SQL Server 인증은 지원되지 않습니다.
프로덕션 워크로드의 경우 새 연결에서 자격 증명 체인 검색 오버헤드를 방지하려면 ActiveDirectoryDefault 대신 fedauth 모드를 명시적으로 사용하는 것이 좋습니다.
Fabric의 SQL 데이터베이스는 Microsoft Entra ID 인증을 지원하는 go-mssqldb 드라이버를 지원합니다:
db, err := sql.Open("azuresql",
"sqlserver://<server>.database.fabric.microsoft.com?database=<database>&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
panic(err)
}
Azure SQL 성능 팁
| 팁 (조언) | 세부 정보 |
|---|---|
| 연결 풀링 사용 | Azure SQL은 각 열린 연결을 tier limit에 포함시킵니다.
MaxOpenConns을 제한된 상태로 유지하세요. |
encrypt=strict를 활성화합니다. |
가장 강력한 보안을 위해 TDS 8.0 암호화를 사용하세요: encrypt=strict. Azure SQL Database는 strict 모드를 지원합니다. |
ApplicationIntent=ReadOnly 사용 |
읽기 중심 쿼리를 읽기 복제본으로 라우팅하기: ApplicationIntent=ReadOnly. 프리미엄, 비즈니스 크리티컬, 하이퍼스케일 티어에서 이용 가능합니다. |
| DTU/vCore 사용 모니터링 | CPU, IO 또는 워커 사용량이 높다면 티어의 규모가 부족할 수 있음을 의미합니다. Azure Monitor를 사용해 자원 활용도를 추적하세요. |
| 거래 시간은 짧게 하세요 | Azure SQL은 자원 임계값을 초과하는 트랜잭션이 있는 세션을 종료합니다(오류 40549). |
| 지역별 엔드포인트 사용 | 애플리케이션을 데이터베이스와 같은 Azure 지역에 배치해 지연을 최소화하세요. |
Azure SQL 문제 해결 체크리스트
| 증상 | 가능한 원인 | 해결 방법 |
|---|---|---|
Cannot open server |
방화벽 규칙이 누락됨 | IP를 추가하거나 Azure 서비스 접근 권한을 활성화하세요. |
Login failed |
잘못된 자격 증명 또는 데이터베이스 사용자 누락 | 로그인이 존재하고 데이터베이스 접근 권한이 있는지 확인하세요. |
| 연결 타임아웃이 간헐적으로 발생합니다 | 서버 재구성 또는 장애 조치 | 재시도 로직과 연결 회전을 구현하세요. |
Resource limit reached |
너무 많은 동시 연결 |
MaxOpenConns을 줄이고 연결을 즉시 닫으세요. |
The service is currently busy |
Azure SQL throttling | 지수 백오프를 사용하여 다시 시도합니다. 규모를 높이는 것도 고려해 보세요. |
| 정상적으로 작동하다가 쿼리 속도가 느려짐 | DTU/vCore 고갈 | Azure Monitor 지표를 확인해보세요. 쿼리를 확장하거나 최적화하세요. |