driver go-mssqldb di Microsoft per SQL Server

Il go-mssqldb driver è il driver ufficiale di Microsoft Go per Microsoft SQL. È un'implementazione puramente Go del protocollo TDS (Tabular Data Stream) che utilizza l'interfaccia standard database/sql . Non richiede ODBC né altre librerie C.

Il driver collega le applicazioni Go a tutte le versioni supportate di SQL Server, database SQL di Azure, Istanza gestita di SQL di Azure, SQL in Fabric, Fabric Data Warehouse e Azure Synapse Analytics su Windows, Linux e macOS.

Scegliere il punto di partenza

Baseline di produzione per Azure SQL

Usa questo esempio come punto di partenza per una connessione Azure SQL orientata alla produzione. Combina identità gestita, impostazioni TLS esplicite, impostazioni del pool con limiti definiti, timeout definiti per richiesta, logica di ritentativi transitori con jitter e logging strutturato.

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

Questo esempio richiede le variabili di ambiente SQL_SERVER e SQL_DATABASE.

Variabili ambientali opzionali:

  • SQL_FEDAUTH (predefinito: ActiveDirectoryManagedIdentity)
  • SQL_APP_NAME (predefinito: go-mssqldb-example)
  • SQL_STARTUP_TIMEOUT (predefinito: 30s, analizzato con time.ParseDuration)

Per ulteriori informazioni su ciascuna parte di questo esempio, consulta database SQL di Azure, pooling delle connessioni, gestione degli errori e modelli di ripetizione dei tentativi e registrazione e diagnostica.

Funzionalità principali

  • Pure Go: Non richiede CGo né dipendenze esterne in C.
  • Tre formati di stringa di connessione: URL (sqlserver://), ADO (key=value) e ODBC (odbc:key=value).
  • Autenticazione di Microsoft Entra ID: Più tipi di credenziali tramite il pacchetto azuread, tra cui identità gestita, entità servizio e identità del carico di lavoro.
  • SQL Server e autenticazione di Windows: Supporta autenticazione SQL, NTLM, Kerberos e single sign-on (SSO) su Windows.
  • Always Encrypted: crittografia lato client con provider di chiavi per certificato locale, Windows Certificate Store e Azure Key Vault.
  • Copia in massa: operazioni di inserimento in blocco ad alte prestazioni.
  • Parametri a valori di tabella (TVP): Passano dati strutturati alle stored procedure.
  • Protocolli multipli: TCP, pipe nominati, memoria condivisa e Dedicated Administrator Connection (DAC).
  • Crittografia TDS 8.0: Crittografia end-to-end con modalità rigorosa.

Per iniziare

Article Descrzione
Installazione e requisiti di sistema Installa il modulo driver e verifica l'ambiente del tuo Go.
Avvio rapido: Connettiti e interroga Connettiti a un'istanza locale o testa SQL Server ed esegui la tua prima query in pochi minuti.
Esegui la migrazione da altri driver Passa da lib/pq, pgx o go-sql-driver/mysql a go-mssqldb.

Configurare le connessioni

Article Descrzione
Stringhe di connessione Formati delle stringhe di connessione URL, ADO e ODBC con esempi.
Opzioni di connessione Timeout, dimensione del pacchetto, failover, SessionInitSQL e NewConnector.
Crittografia e certificati modalità di crittografia TLS, validazione dei certificati e TDS 8.0.
Autenticazione di SQL Server e di Windows Autenticazione SQL, NTLM, Kerberos e configurazione SSO.
Autenticazione Microsoft Entra ID Opzioni di connessione, flussi di credenziali ed esempi di provider di token per Microsoft Entra ID.
Procedure consigliate per la sicurezza Prevenzione dell'iniezione SQL, gestione dei segreti, crittografia e minor privilegio.

Uso dei dati

Article Descrzione
Mapping dei tipi di dati Tabella di conversione dei tipi da Go a SQL e tipi specifici del driver.
Interrogazioni e istruzioni Query parametrizzate, Exec, Query, QueryRow e più insiemi di risultati.
Transazioni Livelli di isolamento, punti di salvataggio, rilevamento dei deadlock e schemi di ritentativo.
Gestione degli errori e schemi di tentativi Struttura degli errori di SQL Server, rilevamento degli errori transitori e retrocesso esponenziale.
Procedure memorizzate Parametri di output, ReturnStatus, e insiemi di risultati delle procedure.
Operazioni di massa Inserimento in blocco ad alte prestazioni con CopyIn.
Parametri con valori di tabella Passa dati strutturati a stored procedure con mssql.TVP.
Dati JSON e XML Interroga, inserisci e trasforma dati JSON e XML con FOR JSON, OPENJSON, e FOR XML.
Sempre criptato Crittografia lato client con provider locali di certificati, Windows Certificate Store e Azure Key Vault.

Distribuire e gestire

Article Descrzione
Pool di connessioni Configura il database/sql pool di connessioni.
Programmazione concorrente Sicurezza goroutine, gruppi di lavoratori, interrogazioni parallele e spegnimento elegante.
Ottimizzazione delle prestazioni Accordatura del pool, dimensione del pacchetto, dichiarazioni preparate e copia in massa.
Database SQL di Azure Autenticazione senza password, limiti di connessione, throttling e gestione del failover.
Risoluzione dei problemi Errori comuni, configurazione della registrazione e diagnostica dei certificati.
Test in corso Modelli di test di integrazione e configurazione del database di test.

Guide a piattaforme e protocolli

Article Descrzione
Linux e macOS Configurazione multipiattaforma, percorsi Kerberos, NTLM e certificati.
Protocolli TCP, named pipe, memoria condivisa, DAC e SQL Browser.
Registrazione e diagnostica Log flag, SetLogger, e SetContextLogger.

Reference

Article Descrzione
Limitazioni Limitazioni dei driver, inclusi LastInsertId, le tabelle temporanee e i vincoli di Always Encrypted.
Novità Cronologia delle versioni e punti salienti delle release per il fork Microsoft del driver.
Supporto e ciclo di vita Matrice di compatibilità delle versioni di Go e SQL Server.