Driver go-mssqldb da Microsoft para SQL Server

O go-mssqldb driver é o driver oficial do Microsoft Go para Microsoft SQL. É uma implementação puramente Go do protocolo TDS (Tabular Data Stream) que usa a interface padrão database/sql . Não requer ODBC nem outras bibliotecas C.

O driver conecta aplicações Go a todas as versões suportadas de SQL Server, Banco de Dados SQL do Azure, Instância Gerenciada de SQL do Azure, SQL em Fabric, Fabric Data Warehouse e Azure Synapse Analytics no Windows, Linux e macOS.

Escolha o ponto de partida

Linha de base de produção para SQL do Azure

Use este exemplo como ponto de partida para uma conexão SQL do Azure orientada à produção. Ele combina identidade gerenciada, configurações explícitas de TLS, configurações de pool com limites definidos, tempos limite com escopo por solicitação, lógica de repetição transitória com jitter e log estruturado.

package main

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"log/slog"
	"math/rand"
	"net/url"
	"os"
	"time"

	mssql "github.com/microsoft/go-mssqldb"
	_ "github.com/microsoft/go-mssqldb/azuread"
)

const (
	maxAttempts    = 4
	baseBackoff    = 200 * time.Millisecond
	maxBackoff     = 3 * time.Second
	queryTimeout   = 2 * time.Second
	startupTimeoutDefault = 30 * time.Second
)

func main() {
	baseLogger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
		Level: slog.LevelInfo,
	}))

	server, ok := getenvRequired("SQL_SERVER")
	if !ok {
		baseLogger.Error("invalid configuration", "error", "missing SQL_SERVER")
		os.Exit(1)
	}

	database, ok := getenvRequired("SQL_DATABASE")
	if !ok {
		baseLogger.Error("invalid configuration", "error", "missing SQL_DATABASE")
		os.Exit(1)
	}

	fedAuth := getenvOrDefault("SQL_FEDAUTH", "ActiveDirectoryManagedIdentity")
	appName := getenvOrDefault("SQL_APP_NAME", "go-mssqldb-example")
	startupTimeout := getenvDurationOrDefault("SQL_STARTUP_TIMEOUT", startupTimeoutDefault)
	logger := baseLogger.With(
		slog.String("server", server),
		slog.String("database", database),
		slog.String("fedauth", fedAuth),
		slog.String("appName", appName),
	)

	connString := buildConnString(server, database, appName, fedAuth)

	db, err := sql.Open("azuresql", connString)
	if err != nil {
		logger.Error("open database", "error", err)
		os.Exit(1)
	}
	defer db.Close()

	db.SetMaxOpenConns(20)
	db.SetMaxIdleConns(10)
	db.SetConnMaxIdleTime(2 * time.Minute)
	db.SetConnMaxLifetime(5 * time.Minute)

	rootCtx := context.Background()

	startupCtx, cancel := context.WithTimeout(rootCtx, startupTimeout)
	defer cancel()
	err = withRetry(startupCtx, logger, func(ctx context.Context) error {
		return db.PingContext(ctx)
	})
	if err != nil {
		logger.Error("ping database", "error", err)
		os.Exit(1)
	}

	var databaseName string
	err = withRetry(rootCtx, logger, func(ctx context.Context) error {
		queryCtx, cancel := context.WithTimeout(ctx, queryTimeout)
		defer cancel()

		return db.QueryRowContext(queryCtx, "SELECT DB_NAME()").Scan(&databaseName)
	})
	if err != nil {
		logger.Error("query database", "error", err)
		os.Exit(1)
	}

	logger.Info("database ready", "database", databaseName)
}

func withRetry(ctx context.Context, logger *slog.Logger, fn func(context.Context) error) error {
	var lastErr error

	for attempt := 1; attempt <= maxAttempts; attempt++ {
		lastErr = fn(ctx)
		if lastErr == nil {
			return nil
		}

		if !isTransient(lastErr) || attempt == maxAttempts {
			return lastErr
		}

		delay := backoffWithJitter(baseBackoff, maxBackoff, attempt)
		logger.WarnContext(ctx, "transient SQL error; retrying",
			"attempt", attempt,
			"delay", delay.String(),
			"error", lastErr,
		)

		timer := time.NewTimer(delay)
		select {
		case <-ctx.Done():
			timer.Stop()
			return ctx.Err()
		case <-timer.C:
		}
	}

	return lastErr
}

func backoffWithJitter(baseDelay, maxDelay time.Duration, attempt int) time.Duration {
	delay := baseDelay * time.Duration(1<<(attempt-1))
	if delay > maxDelay {
		delay = maxDelay
	}

	jitterFraction := 0.20
	multiplier := (1 - jitterFraction) + rand.Float64()*(2*jitterFraction)
	return time.Duration(float64(delay) * multiplier)
}

func buildConnString(server, database, appName, fedAuth string) string {
	query := url.Values{
		"database":               []string{database},
		"fedauth":                []string{fedAuth},
		"encrypt":                []string{"true"},
		"TrustServerCertificate": []string{"false"},
		"app name":               []string{appName},
		"log":                    []string{"1"},
	}

	return fmt.Sprintf("sqlserver://%s?%s", server, query.Encode())
}

func getenvRequired(key string) (string, bool) {
	value := os.Getenv(key)
	if value == "" {
		return "", false
	}
	return value, true
}

func getenvOrDefault(key, defaultValue string) string {
	value, ok := getenvRequired(key)
	if !ok {
		return defaultValue
	}
	return value
}

func getenvDurationOrDefault(key string, defaultValue time.Duration) time.Duration {
	value := os.Getenv(key)
	if value == "" {
		return defaultValue
	}

	parsed, err := time.ParseDuration(value)
	if err != nil {
		return defaultValue
	}

	return parsed
}

func isTransient(err error) bool {
	var sqlErr mssql.Error
	if !errors.As(err, &sqlErr) {
		return false
	}

	switch sqlErr.Number {
	case
		// Connection-establishment and transport transient errors.
		64, 233, 4060, 4221,
		10053, 10054,
		10928, 10929,

		// Azure SQL failover, throttling, and availability errors.
		40020, 40143, 40166,
		40197, 40501, 40540, 40613,
		42108, 42109,
		49918, 49919, 49920,

		// Common retryable statement-level contention errors.
		1205, 1222:
		return true
	default:
		return false
	}
}

Este exemplo requer as variáveis de ambiente SQL_SERVER e SQL_DATABASE.

Variáveis opcionais do ambiente:

  • SQL_FEDAUTH (padrão: ActiveDirectoryManagedIdentity)
  • SQL_APP_NAME (padrão: go-mssqldb-example)
  • SQL_STARTUP_TIMEOUT (padrão: 30s, analisado com time.ParseDuration)

Para mais informações sobre cada parte deste exemplo, consulte Banco de Dados SQL do Azure, pool de conexões, tratamento de erros e padrões de nova tentativa e logs e diagnósticos.

Características principais

  • Pure Go: Não requer CGo nem dependências externas em C.
  • Três formatos de cadeia de conexão: URL (sqlserver://), ADO (key=value) e ODBC (odbc:key=value).
  • Autenticação do Microsoft Entra ID: vários tipos de credenciais por meio do pacote azuread, incluindo identidade gerenciada, entidade de serviço e identidade de carga de trabalho.
  • SQL Server e autenticação do Windows: Suporta autenticação SQL, NTLM, Kerberos e single log-on (SSO) no Windows.
  • Always Encrypted: Criptografia do lado do cliente com provedores de chave de certificados locais, Windows Certificate Store e Azure Key Vault.
  • Cópia em massa: operações de inserção em massa de alto desempenho.
  • Parâmetros com valor de tabela (TVP): Permitem passar dados estruturados para procedimentos armazenados.
  • Vários protocolos: TCP, pipes nomeados, memória compartilhada e DAC (Conexão de Administrador Dedicada).
  • Criptografia TDS 8.0: Criptografia de ponta a ponta com modo estrito.

Introdução

Artigo Description
Instalação e requisitos do sistema Instale o módulo de driver e verifique seu ambiente Go.
Início Rápido: Conecte-se e consulte Conecte-se a uma instância local ou teste do SQL Server e execute sua primeira consulta em minutos.
Migrar de outros drivers Migre de lib/pq, pgx ou go-sql-driver/mysql para go-mssqldb.

Configurar conexões

Artigo Description
Strings de conexão Formatos de cadeia de conexão de URL, ADO e ODBC com exemplos.
Opções de conexão Tempos limite, tamanho do pacote, failover, SessionInitSQL e NewConnector.
Criptografia e certificados Modos de criptografia TLS, validação de certificados e TDS 8.0.
Autenticação do SQL Server e do Windows Autenticação SQL, NTLM, Kerberos e configuração SSO.
Autenticação da ID do Microsoft Entra Opções de conexão com o Microsoft Entra ID, fluxos de credenciais e exemplos de provedores de tokens.
Melhores práticas de segurança Prevenção de injeção SQL, gerenciamento de segredos, criptografia e privilégio mínimo.

Trabalhar com dados

Artigo Description
Mapeamentos de tipo de dados Tabela de conversão de tipos de Go para SQL e tipos específicos do driver.
Consultas e declarações Consultas parametrizadas, Exec, Query, QueryRow, e múltiplos conjuntos de resultados.
Transações Níveis de isolamento, pontos de restauração, detecção de deadlock e padrões de nova tentativa.
Padrões de tratamento de erros e retentativas Estrutura de erro do SQL Server, detecção de erros transitórios e retrocesso exponencial.
Procedimentos armazenados Parâmetros de saída, ReturnStatus, e conjuntos de resultados a partir dos procedimentos.
Operações em lote Inserção em massa de alto desempenho com CopyIn.
Parâmetros com valor de tabela Passe dados estruturados para procedimentos armazenados com mssql.TVP.
Dados JSON e XML Consulte, insera e transforme dados JSON e XML com FOR JSON, OPENJSON, e FOR XML.
Sempre Criptografado Criptografia do lado do cliente com provedores de certificados locais, Windows Certificate Store e Azure Key Vault.

Implantar e operar

Artigo Description
Agrupamento de conexões Configure o pool de database/sql conexões.
Programação simultânea Segurança das goroutines, pools de trabalho, consultas paralelas e desligamento normal.
Otimização do desempenho Ajuste de pool, tamanho do pacote, instruções preparadas e cópia em massa.
Banco de Dados SQL do Azure Autenticação sem senha, limites de conexão, limitação e controle de failover.
Solução de problemas Erros comuns, configuração de logs e diagnósticos de certificados.
Testando Padrões de teste de integração e configuração de banco de dados de teste.

Guias de plataforma e protocolo

Artigo Description
Linux e macOS Configuração multiplataforma, Kerberos, NTLM e caminhos de certificados.
Protocolos TCP, pipes nomeados, memória compartilhada, DAC e SQL Browser.
Log e diagnóstico Sinalizadores de log, SetLogger, e SetContextLogger.