Microsoft go-mssqldb Treiber für SQL Server

Der Treiber go-mssqldb ist der offizielle Microsoft Go-Treiber für Microsoft SQL. Es handelt sich um eine reine Go-Implementierung des TDS-Protokolls (Tabular Data Stream), die die Standardschnittstelle database/sql verwendet. Es erfordert keine ODBC oder andere C-Bibliotheken.

Der Treiber verbindet Go-Anwendungen mit allen unterstützten Versionen der SQL Server-, Azure SQL-Datenbank-, Azure SQL Managed Instance- und SQL-Datenbanken in Fabric, Fabric Data Warehouse und Azure Synapse Analytics auf Windows, Linux und macOS.

Auswählen des Startpunkts

Produktionsbasisplan für Azure SQL

Nutzen Sie dieses Beispiel als Ausgangspunkt für eine produktionsorientierte Azure SQL-Verbindung. Es kombiniert verwaltete Identität, explizite TLS-Einstellungen, begrenzte Einstellungen für den Pool, anfragebezogene Timeouts, Retry-Logik für vorübergehende Fehler mit Jitter und strukturierte Protokollierung.

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

Diese Stichprobe erwartet SQL_SERVER und SQL_DATABASE Umgebungsvariablen.

Optionale Umgebungsvariablen:

  • SQL_FEDAUTH (Standard: ActiveDirectoryManagedIdentity)
  • SQL_APP_NAME (Standard: go-mssqldb-example)
  • SQL_STARTUP_TIMEOUT (Standard: 30s, geparst mit time.ParseDuration)

Weitere Informationen zu jedem Teil dieses Beispiels finden Sie unter Azure SQL-Datenbank, Connection Pooling, Error Handling and Retry Patterns sowie Logging and Diagnostics.

Wichtigste Funktionen

  • Pure Go: Keine CGo- oder externe C-Abhängigkeiten erforderlich.
  • Drei Verbindungszeichenfolge-Formate: URL (sqlserver://), ADO (key=value) und ODBC (odbc:key=value).
  • Microsoft Entra ID-Authentifizierung: Mehrere Zugangsdaten über das azuread Paket, einschließlich Managed Identity, Service Principal und Workload Identity.
  • SQL Server und Windows-Authentifizierung: Unterstützt SQL-Auth, NTLM, Kerberos und Single Sign-on (SSO) unter Windows.
  • Always Encrypted: Client-seitige Verschlüsselung mit lokalen Zertifikaten, Windows Certificate Store und Azure Key Vault-Schlüsselanbietern.
  • Massenkopieren: Hochleistungsfähige Masseneinfügevorgänge.
  • Tabellenwertige Parameter (TVP): Strukturierte Daten an gespeicherte Prozeduren übergeben.
  • Mehrere Protokolle: TCP, benannte Pipes, gemeinsamer Speicher und Dedicated Administrator Connection (DAC).
  • TDS 8.0-Verschlüsselung: Ende-zu-Ende-Verschlüsselung mit strengem Modus.

Erste Schritte

Artikel Description
Installation und Systemanforderungen Installiere das Treibermodul und überprüfe deine Go-Umgebung.
Quickstart: Verbinden und Abfrage Verbinden Sie sich mit einer lokalen oder Test-SQL Server-Instanz und führen Sie Ihre erste Abfrage in wenigen Minuten aus.
Von anderen Treibern migrieren Migration von lib/pq, pgx oder go-sql-driver/mysql zu go-mssqldb.

Konfigurieren von Verbindungen

Artikel Description
Verbindungszeichenfolgen URL-, ADO- und ODBC-Verbindungszeichenfolge-Formate mit Beispielen.
Verbindungsoptionen Timeouts, Paketgröße, Failover, SessionInitSQL, und NewConnector.
Verschlüsselung und Zertifikate TLS-Verschlüsselungsmodi, Zertifikatsvalidierung und TDS 8.0.
SQL Server und Windows-Authentifizierung SQL-Authentifizierung, NTLM, Kerberos und SSO-Konfiguration.
Microsoft Entra ID-Authentifizierung Microsoft Entra ID-Verbindungsoptionen, Anmeldeinformationsflüsse und Beispiele für Tokenanbieter.
Bewährte Methoden für Sicherheit SQL-Injektionsprävention, Geheimnisverwaltung, Verschlüsselung und das Prinzip der geringsten Rechte.

Mit Daten arbeiten

Artikel Description
Datentypzuordnungen Go-zu-SQL-Typkonvertierungstabelle und treiberspezifische Typen.
Abfragen und Aussagen Parametrisierte Abfragen, Exec, Query, , QueryRowund mehrere Ergebnismengen.
Transaktionen Isolationslevel, Speicherpunkte, Deadlock-Erkennung und Wiederholungsmuster.
Fehlerbehandlung und Wiederholungsmuster SQL Server-Fehlerstruktur, vorübergehende Fehlererkennung und exponentielle Rückführung.
Gespeicherten Prozeduren Ausgabeparameter , ReturnStatus, und Ergebnismengen aus Prozeduren.
Massenaktionen Hochleistungs-Bulk-Einsatz mit CopyIn.
Tabellenwertparameter Übermittelt strukturierte Daten an gespeicherte Prozeduren mit mssql.TVP.
JSON- und XML-Daten Abfrage, Einfügen und transformieren Sie JSON- und XML-Daten mit FOR JSON, OPENJSON, und FOR XML.
Immer verschlüsselt Client-seitige Verschlüsselung mit lokalen Zertifikaten, Windows Certificate Store und Azure Key Vault-Anbietern.

Bereitstellen und Betreiben

Artikel Description
Verbindungspooling Konfigurieren Sie den database/sql Verbindungspool.
Gleichzeitige Programmierung Goroutine-Sicherheit, Worker-Pools, parallele Abfragen und elegante Abschaltungen.
Leistungsoptimierung Optimierung des Verbindungspools, Paketgröße, vorbereitete SQL-Anweisungen und Massendatenkopie.
Azure SQL-Datenbank Passwortlose Authentifizierung, Verbindungsbegrenzungen, Drosselung und Failover-Handling.
Problembehandlung Häufige Fehler, Protokollkonfiguration und Zertifikatsdiagnostik.
Testen Integration, Testmuster und Einrichtung der Testdatenbank.

Plattform- und Protokollführer

Artikel Description
Linux und macOS Plattformübergreifende Einrichtung, Kerberos, NTLM und Zertifikatspfade.
Protokolle TCP, benannte Pipes, gemeinsamer Speicher, DAC und SQL-Browser.
Protokollierung und Diagnose Log-Flags, SetLogger, und SetContextLogger.

Reference

Artikel Description
Einschränkungen Treiberbeschränkungen, darunter LastInsertId, Einschränkungen bei temporären Tabellen und Always Encrypted.
Neuerungen Versionsgeschichte und Veröffentlichungshighlights für den Microsoft-Fork des Treibers.
Unterstützung und Lebenszyklus Kompatibilitätsmatrix für Go und SQL-Server-Versionen.