Microsoft go-mssqldb driver voor SQL Server

De go-mssqldb driver is de officiële Microsoft Go-driver voor Microsoft SQL. Het is een pure Go-implementatie van het TDS (Tabular Data Stream) protocol dat gebruikmaakt van de standaardinterface database/sql . Het vereist geen ODBC of andere C-bibliotheken.

De driver verbindt Go-applicaties met alle ondersteunde versies van SQL Server, Azure SQL Database, Azure SQL Managed Instance, SQL-databases in Fabric, Fabric Data Warehouse en Azure Synapse Analytics op Windows, Linux en macOS.

Uw beginpunt kiezen

Productiebasislijn voor Azure SQL

Gebruik dit voorbeeld als uitgangspunt voor een productiegerichte Azure SQL-verbinding. Dit combineert beheerde identiteit, expliciete TLS-instellingen, begrensde poolinstellingen, time-outs per aanvraag, retrylogica voor tijdelijke fouten met jitter en gestructureerde logging.

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

Dit voorbeeld verwacht de omgevingsvariabelen SQL_SERVER en SQL_DATABASE.

Optionele omgevingsvariabelen:

  • SQL_FEDAUTH (standaard: ActiveDirectoryManagedIdentity)
  • SQL_APP_NAME (standaard: go-mssqldb-example)
  • SQL_STARTUP_TIMEOUT (standaard: 30s, geparseerd met time.ParseDuration)

Voor meer informatie over elk onderdeel van dit voorbeeld, zie Azure SQL Database, Connection pooling, Error handling and retry patterns, en Logging and diagnostics.

Belangrijkste kenmerken

  • Pure Go: Geen CGo- of externe C-afhankelijkheden nodig.
  • Drie indelingen voor verbindingsreeksen: URL (sqlserver://), ADO (key=value), en ODBC (odbc:key=value).
  • Microsoft Entra ID-authenticatie: Meerdere soorten inloggegevens via het azuread pakket, waaronder beheerde identiteit, diensthoofd en workloadidentiteit.
  • SQL Server en Windows authentication: Ondersteunt SQL-authenticatie, NTLM, Kerberos en single sign-on (SSO) op Windows.
  • Altijd versleuteld: Client-side versleuteling met lokale certificaten, Windows Certificate Store en Azure Key Vault-sleutelproviders.
  • Bulk kopiëren: Snelle bulk-invoegbewerkingen.
  • Parameters met tabelwaarden (TVP): Geef gestructureerde gegevens door aan stored procedures.
  • Meerdere protocollen: TCP, benoemde pijpen, gedeeld geheugen en Dedicated Administrator Connection (DAC).
  • TDS 8.0-encryptie: End-to-end encryptie met strikte modus.

Get started

Artikel Beschrijving
Installatie- en systeemvereisten Installeer de drivermodule en verifieer je Go-omgeving.
Snelstart: Verbinding maken en query's uitvoeren Maak verbinding met een lokale of test-SQL Server-instantie en voer je eerste query binnen enkele minuten uit.
Migreren vanaf andere stuurprogramma's Migreer van lib/pq, pgx of go-sql-driver/mysql naar go-mssqldb.

Verbindingen configureren

Artikel Beschrijving
Verbindingsreeksen URL-, ADO- en ODBC-verbindingsreeks-formaten met voorbeelden.
Verbindingsopties Time-outs, pakketgrootte, failover, SessionInitSQL, en NewConnector.
Encryptie en certificaten TLS-encryptiemodi, certificaatvalidatie en TDS 8.0.
SQL Server en Windows authentication Configuratie van SQL-authenticatie, NTLM, Kerberos en SSO.
Microsoft Entra-ID-verificatie Microsoft Entra ID-verbindingsopties, inloggegevensstromen en voorbeelden van tokenproviders.
Aanbevolen procedures voor beveiliging SQL-injectiepreventie, secretsbeheer, encryptie en least privilege.

Werken met gegevens

Artikel Beschrijving
Gegevenstypetoewijzingen Tabel voor typeconversie van Go naar SQL en driver-specifieke types.
Queries en statements Geparametriseerde queries, Exec, Query, , QueryRowen meerdere resultaatsets.
Transacties Isolatieniveaus, savepoints, deadlock-detectie en retrypatronen.
Foutafhandeling en patronen voor herpogingen SQL Server foutstructuur, tijdelijke foutdetectie en exponentiële backoff.
Opgeslagen procedures Uitvoerparameters, ReturnStatus, en resultaatverzamelingen van procedures.
Bulkacties Bulkinvoeging met hoge prestaties met CopyIn.
Parameters met tabelwaarde Geef gestructureerde data door aan opgeslagen procedures met mssql.TVP.
JSON- en XML-gegevens Zoek JSON- en XML-gegevens op, voeg in en transformeer ze met FOR JSON, OPENJSON, en FOR XML.
Altijd versleuteld Client-side encryptie met lokale certificaten, Windows Certificate Store en Azure Key Vault-providers.

Implementeren en gebruiken

Artikel Beschrijving
Groepsgewijze verbindingen Configureer de database/sql verbindingspool.
Gelijktijdige programmering Goroutine veiligheid, worker pools, parallelle queries en elegante afsluiting.
Performance-optimalisatie Afstemming van de pool, pakketgrootte, voorbereide instructies en bulkkopie.
Azure SQL Database Wachtwoordloze authenticatie, verbindingslimieten, throttling en failover-afhandeling.
Troubleshooting Veelvoorkomende fouten, logconfiguratie en certificaatdiagnostiek.
Testen Integratie, testpatronen en opzet van testdatabases.

Platform- en protocolhandleidingen

Artikel Beschrijving
Linux en macOS Platformonafhankelijke configuratie, Kerberos, NTLM en certificaatpaden.
Protocollen TCP, benoemde pijpen, gedeeld geheugen, DAC en SQL Browser.
Logboekregistratie en diagnostische gegevens Logvlaggen, SetLogger, en SetContextLogger.