Microsoft go-mssqldb-drivrutin för SQL Server

Drivrutinen go-mssqldb är den officiella Microsoft Go-drivrutinen för Microsoft SQL. Det är en ren Go-implementation av TDS (Tabular Data Stream)-protokollet som använder standardgränssnittet database/sql . Det kräver inte ODBC eller andra C-bibliotek.

Drivrutinen kopplar Go-applikationer till alla stödda versioner av SQL Server, Azure SQL Database, Azure SQL Managed Instance, SQL-databaser i Fabric, Fabric Data Warehouse och Azure Synapse Analytics på Windows, Linux och macOS.

Välj startpunkt

Produktionsbaslinje för Azure SQL

Använd detta exempel som utgångspunkt för en produktionsorienterad Azure SQL-anslutning. Den kombinerar hanterad identitet, explicita TLS-inställningar, begränsade inställningar för anslutningspoolen, timeoutar per begäran, jitterbaserad logik för tillfälliga återförsök och strukturerad loggning.

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

Detta exempel förutsätter miljövariablerna SQL_SERVER och SQL_DATABASE.

Valfria miljövariabler:

  • SQL_FEDAUTH (standardvärde: ActiveDirectoryManagedIdentity)
  • SQL_APP_NAME (standardvärde: go-mssqldb-example)
  • SQL_STARTUP_TIMEOUT (standard: 30s, parsat med time.ParseDuration)

För mer information om varje del av detta exempel, se Azure SQL Database, Connection pooling, Error handling and retry patterns samt Logging and diagnostics.

Viktiga funktioner

  • Pure Go: Inga CGo- eller externa C-beroenden krävs.
  • Tre anslutningssträngsformat: URL (sqlserver://), ADO (key=value), och ODBC (odbc:key=value).
  • Microsoft Entra ID-autentisering: Flera inloggningsuppgifter via paketetazuread, inklusive hanterad identitet, tjänstehuvudperson och arbetsbelastningsidentitet.
  • SQL Server och Windows authentication: Stöder SQL-autentisering, NTLM, Kerberos och single sign-on (SSO) på Windows.
  • Alltid krypterat: Klientbaserad kryptering med lokala certifikat, Windows Certificate Store och Azure Key Vault-nyckelleverantörer.
  • Masskopiering: Högpresterande massinfogningar.
  • Tabellvärdesparametrar (TVP): Skicka strukturerade data till lagrade procedurer.
  • Flera protokoll: TCP, namngivna rör, delat minne och Dedicated Administrator Connection (DAC).
  • TDS 8.0-kryptering: End-to-end-kryptering med strikt läge.

Get started

Artikel Description
Installation och systemkrav Installera drivrutinsmodulen och verifiera din Go-miljö.
Snabbstart: Koppla upp och fråga Koppla upp dig mot en lokal eller test-SQL Server-instans och kör din första fråga på några minuter.
Migrera från andra drivrutiner Migrera från lib/pq, pgx eller go-sql-driver/mysql till go-mssqldb.

Konfigurera anslutningar

Artikel Description
Anslutningssträngar URL-, ADO- och ODBC-reťazec pripojenia-format med exempel.
Anslutningsalternativ Tidsgränser, paketstorlek, redundansväxling, SessionInitSQL, och NewConnector.
Kryptering och certifikat TLS-krypteringsläge, certifikatvalidering och TDS 8.0.
SQL Server och Windows-autentisering SQL-autentisering, NTLM, Kerberos och SSO-konfiguration.
Microsoft Entra ID-autentisering Microsoft Entra ID-anslutningsalternativ, inloggningsflöden och exempel på tokenleverantörer.
Metodtips för säkerhet SQL-injektionsskydd, hemlighetshantering, kryptering och minsta privilegium.

Arbeta med data

Artikel Description
Datatypsmappningar Tabell för typkonvertering från Go till SQL och drivrutinsspecifika typer.
Frågor och uttalanden Parameteriserade frågor, Exec, Query, , QueryRowoch flera resultatmängder.
Transactions Isoleringsnivåer, sparpunkter, dödlåsningsdetektion och återförsöksmönster.
Felhantering och återförsöksmönster SQL Server-felstruktur, identifiering av temporära fel och exponentiell väntetidsökning.
Lagrade procedurer Utdataparametrar, ReturnStatus, och resultatmängder från procedurer.
Massåtgärder Högpresterande bulkinsats med CopyIn.
Tabellvärdesparametrar Skicka strukturerad data till lagrade procedurer med mssql.TVP.
JSON- och XML-data Sök, infoga och transformera JSON- och XML-data med FOR JSON, OPENJSON, och FOR XML.
Alltid krypterad Klientbaserad kryptering med lokala certifikat, Windows Certificate Store och leverantörer av Azure Key Vault.

Distribuera och driva

Artikel Description
Anslutningspoolning Konfigurera anslutningspoolen database/sql .
Samtidigt programutbud Goroutine-säkerhet, arbetarpooler, parallella frågor och smidig avstängning.
Prestandaoptimering Justering av anslutningspool, paketstorlek, förberedda instruktioner och bulkkopiering.
Azure SQL Database Lösenordslös autentisering, anslutningsbegränsningar, strypning och failover-hantering.
Felsökning Vanliga fel, loggningskonfiguration och certifikatdiagnostik.
Testning Integration, testmönster och testdatabasuppsättning.

Plattforms- och protokollguider

Artikel Description
Linux och macOS Plattformsoberoende konfiguration, Kerberos, NTLM och certifikatsökvägar.
Protokoll TCP, namngivna rör, delat minne, DAC och SQL Browser.
Loggning och diagnostik Loggflaggor, SetLogger, och SetContextLogger.