Azure SQL Database で go-mssqldb を使ってください

go-mssqldbドライバーはAzure SQL Database、Azure SQL Managed Instance、SQLデータベースへの接続をMicrosoft Fabricサポートしています。 この記事では、オンプレミスのSQL Serverとは異なるAzure固有の設定、認証、接続制限、トラブルシューティングについて説明します。

Azure SQL Database に接続する

Azure SQL Databaseはデフォルトで暗号化接続が必要です。 encrypt=trueTrustServerCertificate=falseを明示的に指定し、接続がTLSを使用しサーバー証明書を検証するようにしてください:

db, err := sql.Open("sqlserver",
    "sqlserver://<user>:<password>@<server>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false")
if err != nil {
    panic(err)
}

Note

encryptを省略すると、ドライバーは自動的にAzure固有のTLS設定を追加しません。 encrypt=true&TrustServerCertificate=falseはAzure SQL接続線に留めておけ。

Microsoft Entra ID認証は接続文字列からパスワードを除去します。 ActiveDirectoryDefault 環境に最適な資格を自動的に選択し、開発に便利になります:

import (
    "database/sql"
    "log"

    _ "github.com/microsoft/go-mssqldb/azuread"
)

func main() {
    db, err := sql.Open("azuresql",
        "sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
}

Important

ActiveDirectoryDefault 開発には便利ですが、複数の認証情報源を探査するため接続遅延が増加する可能性があります。 本番サービスの場合は、 ActiveDirectoryManagedIdentityActiveDirectoryServicePrincipalのような明示的な方法を好む。

ActiveDirectoryDefaultが認証情報を解決する方法

ActiveDirectoryDefault 以下の認証情報ソースを順番に試し、最初に成功したものを使用します。

Order 資格情報の出典 典型的な環境
1 環境変数(AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_CLIENT_SECRET) CI/CDパイプライン、Dockerコンテナ
2 ワークロード識別子 Azure Workload Identity を使用する Kubernetes Pod
3 マネージド ID Azure VMs, App Service, Container Apps, Azure Functions
4 Azure CLI(az login) ローカル開発
5 Azure Developer CLI(azd auth login) ローカル開発

この認証情報チェーンは開発時に便利 ActiveDirectoryDefault しますが、逐次的なプローブは新しい接続ごとに遅延を増やします。 本番環境では、ドライバーが不要なチェックをスキップできるように、正確な認証方法(例: ActiveDirectoryManagedIdentity)を指定します。

Azureでホストされるアプリケーション(App Service、コンテナアプリ、Azure Functions、またはAzure VMなど)は、明示的なfedauth値を持つマネージドIDを使用するべきです。 この方法は認証チェーンのオーバーヘッドを回避し、環境変数やCLI状態への依存を排除します。

システム割り当てマネージド ID:

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&encrypt=true&TrustServerCertificate=false

ユーザー割り当てマネージド ID(クライアント ID を指定):

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&user id=<client-id>&encrypt=true&TrustServerCertificate=false

データベース内で識別情報へのアクセスを付与します

AzureリソースでマネージドIDを設定した後、含まれたデータベースユーザーを作成します。

CREATE USER [my-app-identity] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [my-app-identity];
ALTER ROLE db_datawriter ADD MEMBER [my-app-identity];

システムに割り当てられたアイデンティティについては、Azureリソース名を使用します。 ユーザー割り当てのアイデンティティについては、アイデンティティ名を使いましょう。

自動化のためのサービスプリンシパル

CI/CDパイプラインやサービス間認証の場合:

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryServicePrincipal&user id=<client-id>&password=<client-secret>&encrypt=true&TrustServerCertificate=false

すべての認証情報タイプについては、Microsoft Entra ID認証を参照してください。

Azureファイアウォールの設定

Azure SQL Databaseはサーバーレベルのファイアウォールを使用しています。 クライアントのパブリックIPアドレスを許可するか、プライベートエンドポイントを使う必要があります。

エラー:サーバーを開けません

このエラーメッセージは、AzureファイアウォールがクライアントのIPアドレスをブロックしていることを示しています:

mssql: login error: Cannot open server '<server>' requested by the login.
Client with IP address '<client-ip>' is not allowed to access the server.

ソリューション:

  1. Azureポータルにファイアウォールルールを追加してください:SQL Server>Networking>ファイアウォールルールを追加してください。
  2. アプリケーションがAzure上で動作している場合は、Azureのサービスとリソースがこのサーバーにアクセスすることを許可してください。
  3. プライベート接続の場合は 、プライベートエンドポイントを設定してください。

エラー:接続タイムアウト

もし接続がタイムアウトしても明確なエラーが出ない場合は、ファイアウォールが静かに接続をブロックしている可能性が高いです。 まずファイアウォールのルールを確認してください。

サービス階層別の接続制限

Azure SQL Databaseはサービス階層に基づいてデータベースごとの接続制限を強制します。 制限を超えると、新しい接続で認証に失敗します。 完全なリミットテーブルについては、 DTU単一データベースリソースリミ ットおよび vCore単一データベースリソースリミットを参照してください。

MaxOpenConnsは自分のティアに合わせて設定します

Azure SQLティアの接続上限より低い値にMaxOpenConnsを設定してください:

// Example for S2 tier (60 max workers).
// Leave headroom for Azure management connections and other clients.
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(5 * time.Minute)

Tip

複数のアプリケーションが同じデータベースを共有している場合、接続制限をすべてのアプリケーションで分割します。 例えば、3つのサービスがS2データベースを共有している場合(最大60人のワーカー)、各サービスに15〜20の接続を割り当てます。

Azure SQL のスロットリングに対処する

Azure SQL Databaseは、データベースがリソース制限(CPU、IO、メモリ、セッション数)に近づくと接続やクエリを制限できます。 スロットリングは、特定のエラー番号という形で現れます。

よくあるスロットリングエラー

エラー番号 メッセージ パターン 原因
10928 Resource ID: %d. The %s limit for the database is %d and has been reached. セッションまたはワーカーの上限に達しました。
10929 Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d. リソースガバナーのスロットリング。
40501 The service is currently busy. 一般的なスロットリング。 再試行してください。
40544 The database has reached its size quota. データベースサイズ制限に達しました。 再挑戦する前に容量を増やすか空きスペースを広げてください。
40549 Session is terminated because you have a long-running transaction. 取引は期限を超えました。
40550 Session is terminated because of too many locks. 過剰なロック取得。
40551 Session is terminated because of excessive tempdb usage. tempdbの過剰使用。
40552 Session is terminated because of excessive transaction log usage. トランザクションログの容量が超過しました。
40553 Session is terminated because of excessive memory usage. 過剰なメモリ消費。
40613 Database '%.*ls' on server '%.*ls' is not currently available. データベースの移動や再構成。
49918 Cannot process request. Not enough resources to process request. リソースの枯渇。
49919 Cannot process create or update request. 同時に作成・更新操作が多すぎます。
49920 Cannot process request. Too many operations in progress. 同時運用制限に達しました。

スロットリングされたリクエストを再試行する

前述の表のほとんどのAzure SQLのスロットリングおよび可用性エラーは一時的なものであり、指数的なバックオフで再試すべきです。 エラー 40544 は一時的なものではありません。 これはデータベースのサイズがノルマに達したため、データベースを拡大するかデータを削除しない限り操作は成功しません。

完全なリトライ実装については、「 エラー処理およびリトライパターン」を参照してください。

import (
    "errors"

    mssql "github.com/microsoft/go-mssqldb"
)

func isAzureThrottling(err error) bool {
    var mssqlErr mssql.Error
    if !errors.As(err, &mssqlErr) {
        return false
    }
    switch mssqlErr.Number {
    case 10928, 10929, 40501, 40549, 40550, 40551, 40552, 40553,
        40613, 49918, 49919, 49920:
        return true
    }
    return false
}

接続の回復力

Azure SQL Databaseは時折、更新、フェイルオーバー、ロードバランシングのためにサーバーを再設定します。 これらのイベントは既存の接続を切り落とし、 driver: bad connection エラーとして浮かび上がります。 プールを自動復旧するように設定してください:

db.SetConnMaxLifetime(5 * time.Minute)  // Rotate connections so stale ones are replaced.
db.SetConnMaxIdleTime(2 * time.Minute)  // Recycle before Azure gateway drops idle connections (30 min).
db.SetMaxIdleConns(10)                  // Keep warm connections for quick recovery.

Note

Azure SQLゲートウェイは約30分間アイドル状態の接続をクローズします。 ConnMaxIdleTimeこの閾値よりかなり下に設定し、アイドル期間後の最初のクエリでdriver: bad connectionエラーを避けてください。 非トランザクションコールの場合、 database/sql 新しい接続で自動的に再試行されます。 トランザクションコールの場合、コードがエラーを検出し、トランザクション全体を再試行しなければなりません。

フェイルオーバー後の再接続

外部取引では、 database/sql が接続不良で開始された通話を、ドライバーが接続を使用不能とマークした場合に、透過的に再試行できます。 この動作は、スロットリングやフェイルオーバー、その他の再試行可能なSQLエラーに対する完全な一時故障再試行ポリシーではありません。 データベース呼び出しをリトライ関数でラップして、これらのシナリオを処理します:

var count int
err := RetryFunc(ctx, DefaultRetryConfig, func(ctx context.Context) error {
    return db.QueryRowContext(ctx, "SELECT COUNT(*) FROM HumanResources.Employee").Scan(&count)
})

実装についてはRetryFuncを参照してください。

Azure SQL Managed Instance

Azure SQL Managed InstanceはオンプレミスのSQL Serverと同じドライバー機能をサポートしていますが、いくつかの違いがあります。

特徴 Azure SQL Database Azure SQL Managed Instance
SQL Server エージェント(SQL サーバー エージェント) 該当なし Available
複数データベースにまたがるクエリ 該当なし Available
連結サーバー 該当なし Available
名前付きパイプ 該当なし 利用不可(TCPのみ)
共有メモリ 該当なし 利用不可(TCPのみ)
Windows 認証 (SSPI) 該当なし マネージドVNet内で利用可能です

Managed Instanceに接続:

sqlserver://<user>:<password>@<instance>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false

Microsoft Fabric の SQL データベース

Important

FabricのSQLデータベースにはMicrosoft Entra ID認証が必要です。 SQL Server認証はサポートされていません。

本番ワークロードでは、新しい接続での認証チェーンプローブのオーバーヘッドを避けるため、fedauthではなく明示的なActiveDirectoryDefaultモードを好む。

FabricのSQLデータベースは、Microsoft Entra ID認証付きのgo-mssqldbドライバーをサポートしています:

db, err := sql.Open("azuresql",
    "sqlserver://<server>.database.fabric.microsoft.com?database=<database>&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
    panic(err)
}

Azure SQL のパフォーマンス向上のヒント

Tip 詳細情報
接続プーリングを使用する Azure SQLは、開いている各接続をティア制限にカウントします。 MaxOpenConnsを縛りつけておけ。
encrypt=strict を有効にする 最も強力なセキュリティを確保するには、TDS 8.0暗号化: encrypt=strictを使用します。 Azure SQL Databaseは厳格モードをサポートしています。
ApplicationIntent=ReadOnly を使用する 読み取り負荷の高いクエリを読み取りレプリカにルーティングする: ApplicationIntent=ReadOnly。 プレミアム、ビジネスクリティカル、ハイパースケールの各ティアで利用可能です。
DTU/vCoreの使用状況を監視してください CPUやIO、ワーカーの使用率が高い場合は、ティアが小規模である可能性があります。 Azure Monitorを使ってリソース利用率を追跡してください。
取引は短くまとめましょう Azure SQLは、リソースの閾値を超えるトランザクションがあるセッションを終了します(エラー40549)。
リージョン エンドポイントの使用 アプリケーションをデータベースと同じAzureリージョンに配置して遅延を最小限にしましょう。

Azure SQL のトラブルシューティング チェックリスト

症状: 考えられる原因 ソリューション
Cannot open server ファイアウォールルールが欠落しています IPアドレスを追加するか、Azureサービスへのアクセスを有効にしてください。
Login failed 認証情報の誤りやデータベースユーザーの欠落 ログインが存在し、データベースにアクセスできるか確認してください。
接続は断続的にタイムアウトします サーバーの再構成またはフェイルオーバー リトライロジックと接続回転を実装してください。
Resource limit reached 同時接続が多すぎる MaxOpenConnsを下げ、すぐに関係を閉じましょう。
The service is currently busy Azure SQL のスロットリング 指数バックオフを使用して再試行します。 スケールアップを検討してください。
正常に動作していた後でクエリが遅くなる DTU/vCoreの枯渇 Azure Monitor metricsをチェックしてください。 クエリを拡大または最適化しましょう。