Używanie go-mssqldb z Azure SQL Database

Sterownik go-mssqldb umożliwia nawiązywanie połączenia z Azure SQL Database, Azure SQL Managed Instance oraz bazą danych SQL w usłudze Microsoft Fabric. Ten artykuł opisuje specyficzną konfigurację, uwierzytelnianie, limity połączenia oraz rozwiązywanie problemów z Azure, które różnią się od lokalnego SQL Server.

Nawiązywanie połączenia z usługą Azure SQL Database

Azure SQL Database domyślnie wymaga szyfrowanych połączeń. Określ encrypt=true i TrustServerCertificate=false wyraźnie tak, aby połączenie korzystało z TLS i weryfikowało certyfikat serwera:

db, err := sql.Open("sqlserver",
    "sqlserver://<user>:<password>@<server>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false")
if err != nil {
    panic(err)
}

Note

Gdy pominiesz encrypt, sterownik nie dodaje automatycznie specyficznych dla Azure ustawień TLS. Zachowaj encrypt=true&TrustServerCertificate=false w parametrach połączenia Azure SQL.

Uwierzytelnianie Microsoft Entra ID eliminuje hasła z twoich ciągów połączeń. ActiveDirectoryDefault automatycznie wybiera najlepsze dostępne poświadczenie w danym środowisku, co jest wygodne podczas programowania:

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()
}

Ważna

ActiveDirectoryDefault jest wygodny do rozwoju, ale może zwiększyć opóźnienia połączenia, ponieważ sprawdza wiele źródeł poświadczeń. Dla usług produkcyjnych preferujemy metodę jawną, taką jak ActiveDirectoryManagedIdentity lub ActiveDirectoryServicePrincipal.

Jak ActiveDirectoryDefault rozwiązuje poświadczenia uwierzytelniające

ActiveDirectoryDefault próbuje kolejno następujących źródeł poświadczeń i używa pierwszego, które zadziała:

Order Źródło uprawnień Typowe środowisko
1 Zmienne środowiskowe (AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET) Potoki CI/CD, kontenery Docker
2 Tożsamość zadania Pody Kubernetes z Azure Workload Identity
3 Tożsamość zarządzana Azure VMs, App Service, Container Apps, Azure Functions
4 Azure CLI (az login) Rozwój lokalny
5 Azure Developer CLI (azd auth login) Rozwój lokalny

Ten łańcuch poświadczeń sprawia, że ActiveDirectoryDefault jest wygodne podczas programowania, ale sekwencyjne sprawdzanie dodaje opóźnienie do każdego nowego połączenia. W produkcji należy określić dokładną metodę uwierzytelniania (np. ActiveDirectoryManagedIdentity), aby sterownik ominął niepotrzebne kontrole.

Aplikacje hostowane w Azure (App Service, Container Apps, Azure Functions lub Azure VM) powinny korzystać z zarządzanej tożsamości o jawnej fedauth wartości. Takie podejście unika narzutu łańcucha uwierzytelnień i usuwa wszelkie zależności od zmiennych środowiskowych lub stanu CLI.

Tożsamość zarządzana przypisana przez system:

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&encrypt=true&TrustServerCertificate=false

Zarządzana tożsamość przypisana przez użytkownika (podaj identyfikator klienta):

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&user id=<client-id>&encrypt=true&TrustServerCertificate=false

Przyznaj dostęp tożsamości do bazy danych

Po skonfigurowaniu zarządzanej tożsamości w zasobie platformy Azure utwórz użytkownika zawartej bazy danych:

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];

Dla tożsamości przypisanych systemom używaj nazwy zasobu Azure. W przypadku tożsamości przypisanych przez użytkownika użyj nazwy tożsamości.

Jednostka usługi do automatyzacji

Dla potoków CI/CD lub uwierzytelniania między usługami:

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryServicePrincipal&user id=<client-id>&password=<client-secret>&encrypt=true&TrustServerCertificate=false

Aby poznać wszystkie typy poświadczeń, zobacz Microsoft Entra ID uwierzytelnianie.

Skonfiguruj zaporę platformy Azure

Azure SQL Database używa zapory serwerowej. Musisz zezwolić na publiczny adres IP klienta lub korzystać z prywatnego endpointu.

Błąd: Nie można otworzyć serwera

Ten komunikat o błędzie wskazuje, że zapora Azure blokuje adres IP Twojego klienta:

mssql: login error: Cannot open server '<server>' requested by the login.
Client with IP address '<client-ip>' is not allowed to access the server.

Rozwiązania:

  1. Dodaj regułę zapory w portalu Azure: SQL server>Networking>Dodaj regułę zapory.
  2. Włącz opcję Zezwalaj usługom i zasobom Azure na dostęp do tego serwera, jeśli Twoja aplikacja działa w Azure.
  3. Aby uzyskać łączność prywatną, skonfiguruj prywatny punkt końcowy.

Błąd: Czas połączenia się zakończył

Jeśli połączenie się skończy bez wyraźnego błędu, zapora prawdopodobnie blokuje połączenie w ciszy. Najpierw sprawdź reguły zapory.

Limity połączeń według poziomu usług

Azure SQL Database egzekwuje limity połączeń dla każdej bazy danych w zależności od poziomu usług. Przekroczenie limitu powoduje awarie uwierzytelniania nowych połączeń. Pełne tabele limitów można znaleźć w dokumentach Limity zasobów pojedynczej bazy danych DTU oraz Limity zasobów pojedynczej bazy danych vCore.

Ustaw MaxOpenConns tak, aby pasowały do twojego tieru

Zawsze ustaw MaxOpenConns na wartość poniżej limitu połączeń dla warstwy Azure SQL:

// 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)

Wskazówka

Jeśli wiele aplikacji korzysta z tej samej bazy danych, podziel limit połączeń między wszystkie aplikacje. Na przykład, jeśli trzy usługi dzielą bazę danych S2 (maksymalnie 60 pracowników), przydziel 15-20 połączeń na usługę.

Obsługa ograniczania w Azure SQL

Azure SQL Database może ograniczać połączenia i zapytania, gdy baza danych zbliża się do limitów zasobów (CPU, IO, pamięć lub liczba sesji). Ograniczanie przejawia się jako konkretne liczby błędów.

Typowe błędy ograniczania

Numer błędu Wzorzec komunikatu Przyczyna
10928 Resource ID: %d. The %s limit for the database is %d and has been reached. Osiągnięty limit sesji lub pracowników.
10929 Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d. Ograniczanie gubernatora zasobów.
40501 The service is currently busy. Ogólne ograniczanie. Ponów próbę.
40544 The database has reached its size quota. Limit rozmiaru bazy danych osiągnięty. Zwiększ pojemność lub wolną przestrzeń przed ponowną próbą.
40549 Session is terminated because you have a long-running transaction. Transakcja przekroczyła limit czasowy.
40550 Session is terminated because of too many locks. Nadmierne pozyskiwanie zamków.
40551 Session is terminated because of excessive tempdb usage. Nadmierne korzystanie z Tempdb.
40552 Session is terminated because of excessive transaction log usage. Przekroczona ilość miejsca w dzienniku transakcyjnym.
40553 Session is terminated because of excessive memory usage. Nadmierne zużycie pamięci.
40613 Database '%.*ls' on server '%.*ls' is not currently available. Baza danych jest przenoszona lub rekonfigurowana.
49918 Cannot process request. Not enough resources to process request. Wyczerpanie zasobów.
49919 Cannot process create or update request. Zbyt wiele jednoczesnych operacji tworzenia/aktualizacji.
49920 Cannot process request. Too many operations in progress. Osiągnięto limit jednoczesnych operacji.

Ponów ograniczone żądania

Większość błędów związanych z ograniczaniem i dostępnością usługi Azure SQL w poprzedniej tabeli ma charakter przejściowy i należy ponawiać próby z zastosowaniem wykładniczo wydłużanych odstępów. Błąd 40544 nie jest przejściowy. Oznacza to, że baza danych osiągnęła limit rozmiaru, więc operacja nie powiedzie się, dopóki nie powiększysz jej skali lub nie usuniesz danych.

Aby uzyskać pełną implementację powtórek, zobacz Obsługa błędów i wzorce powtórek.

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
}

Odporność połączenia

Azure SQL Database okazjonalnie rekonfiguruje serwery do aktualizacji, failoverów i równoważenia obciążenia. Te zdarzenia zrywają istniejące połączenia, co objawia się błędami driver: bad connection. Skonfiguruj pulę tak, aby automatycznie się odzyskiwała:

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.

Note

Brama Azure SQL zamyka połączenia bezczynne przez około 30 minut. Ustaw ConnMaxIdleTime znacznie poniżej tego progu, aby uniknąć driver: bad connection błędów przy pierwszym zapytaniu po okresie bezczynności. W przypadku wywołań nietransakcyjnych database/sql automatycznie ponawia próbę przy użyciu nowego połączenia. W przypadku wywołań transakcyjnych kod musi wychwycić błąd i ponownie przeprowadzić całą transakcję.

Ponowne połączenie po przełączeniu awaryjnym

Poza transakcjami database/sql może w sposób transparentny ponowić wywołanie, które rozpoczyna się przy użyciu wadliwego połączenia, gdy sterownik oznaczy to połączenie jako niezdatne do użytku. To zachowanie nie stanowi pełnej zasady ponawiania prób w przypadku błędów przejściowych związanych z ograniczaniem przepustowości, przełączaniem awaryjnym lub innymi błędami SQL kwalifikującymi się do ponowienia próby. Opakuj wywołania bazy danych w funkcję powtórki, aby poradzić sobie z takimi sytuacjami:

var count int
err := RetryFunc(ctx, DefaultRetryConfig, func(ctx context.Context) error {
    return db.QueryRowContext(ctx, "SELECT COUNT(*) FROM HumanResources.Employee").Scan(&count)
})

Zobacz wzorce obsługi błędów i ponownych prób dotyczące implementacji RetryFunc.

Azure SQL Managed Instance

Azure SQL Managed Instance obsługuje te same funkcje sterownika co SQL Server lokalny, z kilkoma różnicami:

Funkcja Azure SQL Database Azure SQL Managed Instance
Agent serwera SQL Niedostępne Available
Zapytania obejmujące wiele baz danych Niedostępne Available
Połączone serwery Niedostępne Available
Nazwane kanały Niedostępne Niedostępne (tylko TCP)
Pamięć współdzielona Niedostępne Niedostępne (tylko TCP)
Uwierzytelnianie systemu Windows (SSPI) Niedostępne Dostępne w zarządzanym VNet

Połącz się z Managed Instance:

sqlserver://<user>:<password>@<instance>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false

Baza danych SQL w usłudze Microsoft Fabric

Ważna

Baza danych SQL w Fabric wymaga uwierzytelniania za pomocą Microsoft Entra ID. Uwierzytelnianie SQL Server nie jest obsługiwane.

W przypadku obciążeń produkcyjnych preferuj jawnie określony tryb fedauth zamiast ActiveDirectoryDefault, aby uniknąć narzutu związanego ze sprawdzaniem łańcucha poświadczeń przy nowych połączeniach.

Baza danych SQL w usłudze Fabric obsługuje sterownik go-mssqldb z uwierzytelnianiem Microsoft Entra ID:

db, err := sql.Open("azuresql",
    "sqlserver://<server>.database.fabric.microsoft.com?database=<database>&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
    panic(err)
}

Wskazówki dotyczące wydajności Azure SQL

Wskazówka Szczegóły
Korzystanie z buforowania połączeń Azure SQL wlicza każde otwarte połączenie do limitu warstwy. Utrzymuj MaxOpenConns w granicach.
Włącz encrypt=strict Aby zapewnić najsilniejsze zabezpieczenia, użyj szyfrowania TDS 8.0: encrypt=strict. Azure SQL Database obsługuje tryb ścisły.
Użyj ApplicationIntent=ReadOnly Przekierowanie zapytań o dużej liczbie odczytów na repliki odczytu: ApplicationIntent=ReadOnly. Dostępne na poziomach Premium, Business Critical i Hyperscale.
Monitorowanie użycia DTU/vCore Wysokie zużycie CPU, IO lub pracowników wskazuje, że Twój poziom może być za mały. Użyj Azure Monitor do śledzenia wykorzystania zasobów.
Utrzymuj transakcje krótkie Azure SQL kończy sesje transakcjami przekraczającymi progi zasobów (błąd 40549).
Korzystanie z regionalnych punktów końcowych Umieść aplikację w tym samym regionie Azure co baza danych, aby zminimalizować opóźnienia.

Lista kontrolna rozwiązywania problemów z usługą Azure SQL

Objaw Prawdopodobna przyczyna Rozwiązanie
Cannot open server Brak reguły zapory sieciowej Dodaj swoje IP lub włącz dostęp do usług Azure.
Login failed Błędne dane uwierzytelniające lub brak użytkownika bazy danych Sprawdź, czy login istnieje i ma dostęp do bazy danych.
Przerwy na łączach Rekonfiguracja serwera lub przełączenie awaryjne Wprowadź logikę powtórek i rotację połączeń.
Resource limit reached Zbyt wiele jednoczesnych połączeń Obniż MaxOpenConns i niezwłocznie zamknij połączenia.
The service is currently busy Azure SQL throttling Ponów próbę z wycofywaniem wykładniczym. Rozważ skalowanie.
Wolne zapytania po wcześniejszym poprawnym działaniu Wyczerpanie się zasobów DTU/vCore Sprawdź metryki usługi Azure Monitor. Skaluj lub optymalizuj zapytania.