Utilize o go-mssqldb com o Base de Dados SQL do Azure

O go-mssqldb controlador suporta a ligação ao Base de Dados SQL do Azure, ao Azure SQL Managed Instance e à base de dados SQL no Microsoft Fabric. Este artigo aborda a configuração, autenticação, limites de ligação e resolução de problemas específicas do Azure que diferem do SQL Server local.

Conectar-se ao Banco de Dados SQL do Azure

Base de Dados SQL do Azure requer ligações encriptadas por defeito. Especifique encrypt=true e TrustServerCertificate=false explicitamente para que a ligação use TLS e valide o certificado do servidor:

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

Observação

Quando omites encrypt, o driver não adiciona automaticamente definições TLS específicas do Azure. Mantenha encrypt=true&TrustServerCertificate=false nas cadeias de ligação do SQL do Azure.

A autenticação Microsoft Entra ID elimina palavras-passe das suas cadeias de ligação. ActiveDirectoryDefault seleciona automaticamente a melhor credencial disponível para o ambiente, o que torna o processo conveniente para o desenvolvimento:

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

Importante

ActiveDirectoryDefault é conveniente para o desenvolvimento, mas pode adicionar latência de ligação porque sonda múltiplas fontes de credenciais. Para serviços de produção, prefira um método explícito como ActiveDirectoryManagedIdentity ou ActiveDirectoryServicePrincipal.

Como o ActiveDirectoryDefault obtém as credenciais

ActiveDirectoryDefault tenta as seguintes fontes de credenciais pela seguinte ordem e usa a primeira que tem êxito:

Order Origem da credencial Ambiente típico
1 Variáveis do ambiente (AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET) pipelines de CI/CD, contentores Docker
2 Identidade do fluxo de trabalho Pods do Kubernetes com Azure Workload Identity
3 Identidade gerenciada Azure VMs, App Service, Container Apps, Funções do Azure
4 CLI do Azure (az login) Desenvolvimento local
5 CLI do desenvolvedor do Azure (azd auth login) Desenvolvimento local

Esta cadeia de credenciais torna ActiveDirectoryDefault conveniente durante o desenvolvimento, mas a sondagem sequencial adiciona latência a cada nova ligação. Para produção, especifique o método exato de autenticação (como ActiveDirectoryManagedIdentity) para que o driver evite verificações desnecessárias.

As aplicações alojadas no Azure (App Service, Container Apps, Funções do Azure ou VMs Azure) devem usar uma identidade gerida com um valor explícitofedauth. Esta abordagem evita a sobrecarga da cadeia de credenciais e elimina qualquer dependência de variáveis do ambiente ou do estado da CLI.

Identidade gerenciada atribuída ao sistema:

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

Identidade gerida atribuída pelo utilizador (especificar o ID do cliente):

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

Conceder acesso à identidade na base de dados

Depois de configurar a identidade gerida no recurso Azure, crie um utilizador de base de dados contido:

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

Para identidades atribuídas ao sistema, use o nome do recurso Azure. Para identidades atribuídas pelo utilizador, use o nome de identidade.

Princípio de serviço para automação

Para pipelines CI/CD ou autenticação serviço-a-serviço:

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

Para todos os tipos de credenciais, consulte autenticação Microsoft Entra ID.

Configurar o firewall do Azure

Base de Dados SQL do Azure utiliza um firewall ao nível do servidor. Deve permitir o endereço IP público do seu cliente, ou usar um endpoint privado.

Erro: Não é possível abrir o servidor

Esta mensagem de erro indica que o firewall do Azure está a bloquear o endereço IP do seu cliente:

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

Soluções:

  1. Adicionar uma regra de firewall no portal do Azure: SQL server>Rede>Adicionar uma regra de firewall.
  2. Ativar Permitir que os serviços e recursos do Azure acedam a este servidor se a sua aplicação estiver a correr no Azure.
  3. Para conectividade privada, configure um endpoint privado.

Erro: A ligação expirou

Se a ligação falhar sem um erro claro, o firewall provavelmente está a bloquear a ligação silenciosamente. Verifica primeiro as regras do firewall.

Limites de ligação por nível de serviço

Base de Dados SQL do Azure impõe limites de ligação por base de dados com base no nível de serviço. Exceder o limite causa falhas de autenticação para novas ligações. Para as tabelas completas de limites, veja limites de recurso único da base de dados DTU e limites de recurso único da base de dados vCore.

Defina o MaxOpenConns para corresponder ao seu nível

Defina sempre MaxOpenConns para um valor abaixo do limite de ligações do seu escalão do SQL do Azure:

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

Tip

Se múltiplas aplicações partilharem a mesma base de dados, divida o limite de ligação entre todas as aplicações. Por exemplo, se três serviços partilharem uma base de dados S2 (máximo de 60 trabalhadores), aloque 15-20 ligações por serviço.

Gerir a limitação do SQL do Azure

O Base de Dados SQL do Azure pode limitar ligações e consultas quando a base de dados se aproxima dos limites de recursos (CPU, IO, memória ou número de sessões). A limitação manifesta-se como números de erro específicos.

Erros comuns de estrangulamento

Número do erro Padrão de mensagens Motivo
10928 Resource ID: %d. The %s limit for the database is %d and has been reached. Limite de sessão ou trabalhador atingido.
10929 Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d. Limitação do governador de recursos.
40501 The service is currently busy. Limitação geral. Tente novamente.
40544 The database has reached its size quota. Limite de tamanho da base de dados atingido. Aumente a capacidade ou livre espaço antes de tentar novamente.
40549 Session is terminated because you have a long-running transaction. A transação ultrapassou o limite de tempo.
40550 Session is terminated because of too many locks. Aquisição excessiva de fechaduras.
40551 Session is terminated because of excessive tempdb usage. Uso excessivo de tempdb.
40552 Session is terminated because of excessive transaction log usage. Espaço de registo de transações ultrapassado.
40553 Session is terminated because of excessive memory usage. Consumo excessivo de memória.
40613 Database '%.*ls' on server '%.*ls' is not currently available. Base de dados a ser movida ou reconfigurada.
49918 Cannot process request. Not enough resources to process request. Exaustão de recursos.
49919 Cannot process create or update request. Demasiadas operações simultâneas de criação/atualização.
49920 Cannot process request. Too many operations in progress. Limite de operação simultâneo atingido.

Repetir solicitações sujeitas a limitação

A maioria dos erros de limitação e disponibilidade do SQL do Azure na tabela anterior são transitórios e devem ser repetidos com um intervalo de espera exponencial. Erro 40544 não é transitório. Significa que a base de dados atingiu a sua quota de tamanho, por isso a operação não terá sucesso até escalar a base de dados ou eliminar dados.

Para uma implementação completa de repetição, consulte Padrões de tratamento de erros e repetição.

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
}

Resiliência da ligação

O Base de Dados SQL do Azure ocasionalmente reconfigura servidores para atualizações, failovers e balanceamento de carga. Estes eventos interrompem as ligações existentes, que se manifestam como erros driver: bad connection. Configure o seu pool para recuperar automaticamente:

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.

Observação

O gateway SQL do Azure fecha ligações que estão inativas durante cerca de 30 minutos. Defina ConnMaxIdleTime bem abaixo deste limiar para evitar driver: bad connection erros na primeira consulta após um período de inatividade. Para chamadas não transacionais, database/sql tenta automaticamente uma nova ligação. Para chamadas transacionais, o seu código deve detetar o erro e tentar novamente toda a transação.

Reconexão após failover

Fora das transações, database/sql pode repetir automaticamente, de forma transparente, uma chamada que começa numa má conexão quando o driver marca a conexão como inutilizável. Este comportamento não constitui uma política completa de repetição para falhas transitórias, limitação, ativação pós-falha ou outros erros SQL passíveis de repetição. Encapsule as chamadas à base de dados numa função de repetição para lidar com essas situações:

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

Consulte Tratamento de erros e padrões de nova tentativa relativamente à RetryFunc implementação.

Azure SQL Managed Instance

Azure SQL Managed Instance suporta as mesmas funcionalidades de drivers que o SQL Server on-premiss, com algumas diferenças:

Feature Base de Dados SQL do Azure Azure SQL Managed Instance
Agente do SQL Server Não disponível Available
Consultas entre bancos de dados Não disponível Available
Servidores vinculados Não disponível Available
Canalizações nomeadas Não disponível Não disponível (apenas TCP)
Memória partilhada Não disponível Não disponível (apenas TCP)
Autenticação do Windows (SSPI) Não disponível Disponível dentro do VNet gerido

Ligue-se a uma Instância Gerida:

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

Banco de dados SQL no Microsoft Fabric

Importante

A base de dados SQL no Fabric requer autenticação do Microsoft Entra ID. A autenticação do SQL Server não é suportada.

Para cargas de trabalho de produção, prefira um modo explícito fedauth em vez de ActiveDirectoryDefault para evitar a sobrecarga da sondagem da cadeia de credenciais em novas ligações.

A base de dados SQL no Fabric suporta o controlador go-mssqldb com autenticação do 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)
}

Dicas de desempenho para SQL do Azure

Tip Detalhes
Utilizar o pool de conexões O SQL do Azure contabiliza cada ligação aberta para efeitos do limite do escalão. Mantenha MaxOpenConns limitado.
Ativar encrypt=strict Para a segurança mais forte, use a encriptação TDS 8.0: encrypt=strict. Base de Dados SQL do Azure suporta o modo estrito.
Utilize ApplicationIntent=ReadOnly Encaminhe consultas de leitura intensiva para réplicas de leitura: ApplicationIntent=ReadOnly. Disponível nos níveis Premium, Business Critical e Hyperscale.
Monitorizar a utilização do DTU/vCore Uma utilização elevada de CPU, E/S ou processos de trabalho indica que o seu escalão pode ser insuficiente. Use o Azure Monitor para acompanhar a utilização de recursos.
Mantenha as transações curtas O SQL do Azure termina sessões com transações que excedem os limiares de recursos (erro 40549).
Utilizar pontos finais regionais Coloque a sua aplicação na mesma região do Azure que a base de dados para minimizar a latência.

Checklist de resolução de problemas para SQL do Azure

Symptom Causa provável Solução
Cannot open server Regra de firewall em falta Adicione o seu IP ou ative o acesso aos serviços do Azure.
Login failed Credenciais erradas ou utilizador da base de dados em falta Verifica se o login existe e tem acesso à base de dados.
As ligações expiram de forma intermitente Reconfiguração do servidor ou comutação pós-falha Implemente a lógica de repetição e a rotação de conexões.
Resource limit reached Demasiadas ligações simultâneas Reduza MaxOpenConns e feche as ligações de imediato.
The service is currently busy SQL do Azure throttling Tenta novamente com recuo exponencial. Considera aumentar a escala.
Consultas lentas após terem funcionado bem Esgotamento de DTU/vCore Consulta as métricas do Azure Monitor. Expandir ou otimizar as consultas.