go-mssqldbドライバーはMicrosoft SQLの公式のMicrosoft Goドライバーです。 これはTDS(Tabular Data Stream)プロトコルの純粋なGo実装で、標準 database/sql インターフェースを使用しています。 ODBCや他のCライブラリは必要ありません。
このドライバーを使用すると、Windows、Linux、macOS 上の Go アプリケーションから、サポートされているすべてのバージョンの SQL Server、Azure SQL Database、Azure SQL Managed Instance、Fabric 内の SQL データベース、Fabric Data Warehouse、Azure Synapse Analytics に接続できます。
出発点を選択する
- WindowsでローカルSQL Serverサンプルを素早く動かすには、まずQuickstart: Connectとクエリから始めてください。
- パスワードレス認証でAzure SQLに接続するには、まずAzure SQL DatabaseとMicrosoft Entra ID認証から始めてください。
- PostgreSQLやMySQLからの移行は、 まず他のドライバーからの移行から始めてください。
- 大量のデータを効率的に移動させるには、 バルク操作 や テーブル値パラメータに切り替えてください。
- TLS、証明書、ログインの問題をトラブルシューティングするには、「 暗号化と証明書」 および 「トラブルシューティング」へ行ってください。
Azure SQLの運用ベースライン
このサンプルを本番向けAzure SQL接続の出発点として活用してください。 このソリューションは、マネージド ID、明示的な TLS 設定、バウンドプール設定、要求単位のタイムアウト、ジッターを適用した一時的な再試行ロジック、構造化されたログを組み合わせています。
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
}
}
このサンプルは SQL_SERVER と SQL_DATABASE 環境変数を期待しています。
オプションの環境変数:
-
SQL_FEDAUTH(デフォルト:ActiveDirectoryManagedIdentity) -
SQL_APP_NAME(デフォルト:go-mssqldb-example) -
SQL_STARTUP_TIMEOUT(デフォルト:30s、time.ParseDurationと解析)
このサンプルの各部分の詳細については、「Azure SQL Database」「接続プーリング」「エラー処理と再試行パターン」「ログおよび診断」をご覧ください。
主要な機能
- Pure Go:CGoや外部C依存関係は不要です。
-
3つの接続文字列形式:URL(
sqlserver://)、ADO(key=value)、ODBC(odbc:key=value)。 -
Microsoft Entra ID認証:
azureadパッケージを通じて管理型アイデンティティ、サービスプリンシパル、ワークロード識別など複数の認証情報タイプを利用できます。 - SQL ServerおよびWindows 認証:Windows上でSQL認証、NTLM、Kerberos、シングルサインオン(SSO)をサポートします。
- Always Encrypted:ローカル証明書、Windows証明書ストア、Azure Key Vault鍵提供者によるクライアント側暗号化。
- 一括コピー: 高性能な大量挿入処理。
- テーブル値パラメータ(TVP):構造化データをストアドプロシージャに渡します。
- 複数のプロトコル:TCP、名前付きパイプ、共有メモリ、専用管理者接続(DAC)。
- TDS 8.0暗号化:厳密モードを用いたエンドツーエンド暗号化。
概要
| [アーティクル] | Description |
|---|---|
| 設置およびシステム要件 | ドライバーモジュールをインストールし、Go環境を確認してください。 |
| クイックスタート:接続とクエリ | ローカルまたはテスト用のSQL Serverインスタンスに接続し、最初のクエリを数分で実行してください。 |
| 他のドライバーから移行 | lib/pq、pgx、またはgo-sql-driver/mysqlからgo-mssqldbに移行してください。 |
接続の設定
| [アーティクル] | Description |
|---|---|
| 接続文字列 | URL、ADO、ODBCの接続文字列形式と例。 |
| 接続オプション | タイムアウト、パケットサイズ、フェイルオーバー、 SessionInitSQL、 NewConnector。 |
| 暗号化と証明書 | TLS暗号化モード、証明書検証、TDS 8.0。 |
| SQL Server 認証と Windows 認証 | SQL認証、NTLM、Kerberos、SSOの設定。 |
| Microsoft Entra ID 認証 | Microsoft Entra IDの接続オプション、認証フロー、トークン提供者の例。 |
| セキュリティのベスト プラクティス | SQLインジェクション防止、秘密管理、暗号化、そして最小権限。 |
データの操作
| [アーティクル] | Description |
|---|---|
| データ型のマッピング | Go から SQL への型変換テーブルとドライバー固有の型 |
| クエリと文 | パラメータ化されたクエリ、 Exec、 Query、 QueryRow、そして複数の結果セット。 |
| トランザクション | 隔離レベル、セーブポイント、デッドロック検出、再試行パターンなどです。 |
| エラー処理と再試行パターン | SQL Serverエラー構造、一時的エラー検出、指数関数的バックオフ。 |
| ストアド プロシージャ | プロシージャからパラメータ、 ReturnStatus、結果セットを出力します。 |
| 一括操作 |
CopyIn を使用した高性能な一括挿入。 |
| テーブル値パラメーター | 構造化データを mssql.TVPでストアドプロシージャに渡します。 |
| JSONおよびXMLデータ | JSONおよびXMLデータを FOR JSON、 OPENJSON、 FOR XMLでクエリ、挿入、変換します。 |
| 常に暗号化 | ローカル証明書、Windows証明書ストア、Azure Key Vaultプロバイダーによるクライアントサイド暗号化。 |
デプロイと運用
| [アーティクル] | Description |
|---|---|
| 接続プール |
database/sql接続プールを設定してください。 |
| 並行プログラミング | Goroutine の安全性、ワーカープール、並列クエリ、正常なシャットダウン。 |
| パフォーマンスチューニング | プールの調整、パケット サイズ、準備済みのステートメント、一括コピー。 |
| Azure SQL Database | パスワード不要認証、接続制限、スロットリング、フェイルオーバー処理。 |
| Troubleshooting | よくあるエラー、ログ設定、証明書診断。 |
| テスト | 統合テストパターンとテストデータベースの設定。 |
プラットフォームおよびプロトコルガイド
| [アーティクル] | Description |
|---|---|
| Linux と macOS | クロスプラットフォーム設定、Kerberos、NTLM、証明書パス。 |
| プロトコル | TCP、名前付きパイプ、共有メモリ、DAC、SQLブラウザなどがあります。 |
| ログと診断 | ログフラグ、 SetLogger、 SetContextLogger。 |