mssql-django のトラブルシューティング

Microsoft FabricのSQL Server、Azure SQL Database、Azure SQL Managed Instance、および SQL データベースのmssql-django バックエンドに関する一般的な問題を診断して解決します。

接続に関する問題

このセクションでは、最も一般的な接続エラーとその解決方法について説明します。

ODBC ドライバーが見つかりません

症状:

django.core.exceptions.ImproperlyConfigured: 'ODBC Driver 18 for SQL Server' is not a recognized ODBC driver

または:

Error: ('01000', "[01000] [unixODBC][Driver Manager]Can't open lib 'ODBC Driver 18 for SQL Server'")

考えられる原因と解決策:

  • ODBC ドライバーがインストールされていません

    Microsoft ODBC Driver for SQL Serverをインストールします。 ダウンロード リンクについては、「ODBC Driver for SQL Server のダウンロード」を参照してください。

  • 複数のドライバー バージョンがインストールされている

    settings.pyで正確なドライバー名またはパスを指定します。

    DATABASES = {
        "default": {
            "ENGINE": "mssql",
            "NAME": "<your-database>",
            "USER": "<your-username>",
            "PASSWORD": "<your-password>",
            "HOST": "<your-server>",
            "PORT": "1433",
            "OPTIONS": {
                "driver": "ODBC Driver 17 for SQL Server",
            },
        },
    }
    

    Linux では、完全なパスを指定します。

    "OPTIONS": {
        "driver": "/opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.10.so.6.1",
    },
    
  • インストールされているドライバーを確認する

    • Linux/macOS では、 odbcinst -q -dを実行します。
    • Windows では、管理ツールODBC データ ソース を確認します。

接続が拒否されました

症状:

django.db.utils.OperationalError: ('08001', '[08001] ... TCP Provider: Error code 0x2749 ...')

考えられる原因と解決策:

  • SQL Serverで TCP/IP が有効になっていない

    • SQL Server 構成マネージャー を開きます。
    • [SQL Server ネットワーク構成] で、TCP/IP を有効にします。
    • [TCP/IP プロパティ] で、接続に使用する IP アドレスをアクティブにします。
    • SQL Server サービスを再起動します。
  • ファイアウォールによるポート 1433 のブロック

    • ファイアウォール規則でポート 1433 での受信接続が許可されていることを確認します。
    • Azure SQLの場合は、Azure ポータルのファイアウォール設定にクライアント IP を追加します。
  • 間違ったサーバー名またはポート

    構成の HOSTPORT の値を確認します。

ログインに失敗しました

症状:

django.db.utils.OperationalError: ('28000', "[28000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Login failed for user '<username>'.")

考えられる原因と解決策:

  • 資格情報が正しくありません

    ユーザー名とパスワードを確認します。

  • ユーザーが存在しない

    ログインがターゲット データベースのユーザーにマップされていることを確認します。

  • SQL Server認証が無効になっている

    混合モード認証を有効にするか、WindowsまたはMicrosoft Entra認証を使用します。

接続タイムアウト

症状:

django.db.utils.OperationalError: ('HYT00', '[HYT00] [Microsoft][ODBC Driver 18 for SQL Server]Login timeout expired')

考えられる原因と解決策:

  • ネットワーク待ち時間

    OPTIONS の connection_timeout を増やします。

  • サーバーのオーバーロード

    connection_retriesconnection_retry_backoff_timeを増やします。

    "OPTIONS": {
        "driver": "ODBC Driver 18 for SQL Server",
        "connection_timeout": 30,
        "connection_retries": 5,
        "connection_retry_backoff_time": 10,
    },
    

移行に関する問題

これらのエラーは、SQL Serverに対する Django の移行操作中に発生します。

日付と時刻の問題

Now() 値は、次の場合にシフトされます。 USE_TZ=True

症状:

Django Now()auto_now、またはauto_now_addで書き込まれたタイムスタンプは、SQL Server ホストタイム ゾーンが UTC でない場合にシフトされます。

解決策: mssql-django 1.7.2 以降にアップグレードします。 バージョン 1.7.2 では、SQL 生成と Now() オフセット処理タイム ゾーン対応が修正されました。

AttributeError .explain() の呼び出し時

症状:

AttributeError: ... explain_format ...

解決策: mssql-django 1.7.2 以降にアップグレードします。 バージョン 1.7.2 では、Django 4.0 以降の Explain メタデータのコンパイラ互換性が修正されました。

自動フィールドを変更できません

症状:

django.db.utils.ProgrammingError: Cannot alter column to or from an IDENTITY column

解決策: SQL Serverでは、AutoFieldのフィールドの変更はサポートされていません。 目的のフィールド型で新しいモデルを作成し、データを手動で移行してから、古いテーブルを削除します。 回避策については、「 mssql-django を使用したデータベースの移行」を参照してください。

外部キー制約で名前の変更が失敗する

症状:

django.db.utils.ProgrammingError: ... could not drop constraint ...

解決策: SQL Server列の名前を変更する前に外部キー制約を削除する必要があります。 移行で SeparateDatabaseAndState を使用します。 例については、「 mssql-django を使用したデータベースの移行」を参照してください。

エンコードの問題

エンコード エラーは、通常、pyodbcがSQL Serverから文字データを誤って解釈した場合に発生します。

Unicode エンコード エラー

症状:

UnicodeDecodeError: 'utf-8' codec can't decode byte ...

解決策: pyodbc ディクショナリでOPTIONS エンコードを構成します。

"OPTIONS": {
    "driver": "ODBC Driver 18 for SQL Server",
    "unicode_results": True,
},

FreeTDS の問題

FreeTDS には、Microsoft ODBC ドライバーとは異なる特定の構成が必要です。

host_is_server エラー

症状:

host_is_serverを指定せずに FreeTDS を使用すると、接続が失敗します。

解決策: FreeTDS を使用するときに host_is_serverTrue に設定します。

"OPTIONS": {
    "driver": "FreeTDS",
    "host_is_server": True,
},

FreeTDS 構成の詳細については、「 mssql-django の接続オプション」を参照してください。

データベースの問題をテストする

認証方法によっては、データベースの作成と破棄のテストが失敗する可能性があります。

マネージド ID を使用してテスト データベースを作成できない

症状:

django.db.utils.DatabaseError: ('42000', '[42000] ... EXECUTE permission denied on object ...')

または:

django.db.utils.OperationalError: ('28000', ... login failed ...)

ActiveDirectoryMsi (マネージド ID) 認証を使用すると、テスト ランナーはテスト データベースの作成または破棄に失敗します。 この制限は次の理由で存在します。

  • マネージド ID 資格情報は、ホスト環境 (Azure VM や App Service など) から取得されます。

  • テスト ランナーは、ティアダウン中に test データベースの認証情報を使用して接続しようとします。

  • マネージド ID にはデータベース レベルのロールを付与できますが、通常、テスト データベースの作成と削除には、テスト ランナーにはないサーバー レベルのアクセス許可が必要です。

影響を受ける認証方法:

  • ActiveDirectoryMsi(マネージド ID Azure)
  • ActiveDirectoryServicePrincipal (サーバー スコープでのみ構成されている場合)

サポートされている認証方法 (データベースの作成のテスト機能):

  • ActiveDirectoryPassword
  • ActiveDirectoryIntegrated
  • SQL 認証 (ユーザー名/パスワード)

テスト環境の認証のトレードオフ

Method シークレット不要 自動テスト用DBの作成/削除に対応 一般的な使用方法
ActiveDirectoryMsi Yes 通常、いいえ (サーバー レベルの権限が付与されていない場合) Azureホスト型運用ワークロード
ActiveDirectoryServicePrincipal いいえ (クライアント シークレット/証明書) 付与されたサーバー レベルの権限に依存 明示的な ID 管理を使用した CI/CD
ActiveDirectoryPassword No はい (十分な SQL アクセス許可を持つ) 開発者および制御された CI 環境
SQL 認証 No はい (十分な SQL アクセス許可を持つ) ローカルまたは分離されたテスト環境

解決策:

  • 開発用: --keepdb フラグを使用して、テスト データベースの破棄をスキップします。

    python manage.py test --keepdb
    
  • CI/CD パイプラインの場合: 専用のテスト データベースを事前に作成し、マネージド ID に CREATE TABLEALTER のアクセス許可を付与します。

    -- Connect as a server admin, then:
    USE [test_database_name];
    
    -- Grant permissions for managed identity (replace with your identity name)
    CREATE USER [your-app-identity] FROM EXTERNAL PROVIDER;
    GRANT CREATE TABLE TO [your-app-identity];
    GRANT ALTER ON SCHEMA::dbo TO [your-app-identity];
    
  • 別の方法: テスト環境に SQL 認証を使用するか、CI/CD テスト ランナーの ActiveDirectoryPassword に切り替えます。

ロールバック プロシージャ

移行が途中で失敗した場合は、次のロールバック シーケンスを使用して既知の正常な状態に戻ります。

  1. アプリケーションの書き込みを停止して、スキーマの誤差を回避します。

  2. 移行状態を検査する:

    python manage.py showmigrations
    python manage.py sqlmigrate <app_label> <migration_number>
    
  3. 最後に正常であることが確認されている移行にロールバックします:

    python manage.py migrate <app_label> <previous_migration>
    
  4. スキーマと移行履歴が異なる場合は、実際のデータベース スキーマを検証した後にのみ、 --fake で状態を慎重に修復します。

  5. 最初にステージング環境で移行を再実行してから、運用環境を再試行します。

Important

ドロップ、名前の変更、列の種類の変更などの破壊的な移行の場合は、デプロイの前にテスト済みのバックアップを作成します。 移行によるロールバックが不可能な場合は、バックアップから復元し、検証済みの移行を再適用します。

Docker とコンテナーの問題

コンテナー イメージには、ODBC ドライバーの明示的なインストールとビルドの依存関係が必要です。

コンテナーに ODBC ドライバーが見つかりません

症状:

Error: ('01000', "[01000] [unixODBC][Driver Manager]Can't open lib 'ODBC Driver 18 for SQL Server'")

考えられる原因と解決策:

  • コンテナー イメージに ODBC ドライバーがインストールされていない

    スリムまたは Alpine の基本イメージには、ODBC ドライバーは含まれません。 Microsoft APT リポジトリを追加し、Dockerfile にmsodbcsql18をインストールします。 完全な Dockerfile の例については、「 App Service へのデプロイ 」を参照してください。

  • unixodbc-dev パッケージがありません

    pyodbc ホイールは、libodbc.soに対してリンクします。 Python パッケージをインストールする前に、unixodbc-dev (Debian/Ubuntu) または unixODBC-devel (RHEL/Fedora) をインストールします。

pyodbc がスリムなイメージでビルドできない

症状:

error: command 'gcc' failed: No such file or directory

または:

fatal error: sql.h: No such file or directory

解決策: pip installする前にビルドの依存関係をインストールします。

RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    g++ \
    unixodbc-dev

または、マルチステージ ビルドを使用して、最終的なイメージを小さくします。

# Build stage
FROM python:3.12-slim AS builder
RUN apt-get update && apt-get install -y --no-install-recommends gcc g++ unixodbc-dev
COPY requirements.txt .
RUN pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt

# Runtime stage
FROM python:3.12-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl gnupg2 unixodbc \
    && curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg \
    && curl -fsSL https://packages.microsoft.com/config/debian/12/prod.list > /etc/apt/sources.list.d/mssql-release.list \
    && apt-get update \
    && ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18 \
    && apt-get purge -y --auto-remove curl gnupg2 \
    && rm -rf /var/lib/apt/lists/*
COPY --from=builder /wheels /wheels
RUN pip install --no-cache-dir /wheels/*

コンテナーがSQL Serverに接続できない

症状:

django.db.utils.OperationalError: ('08001', '... TCP Provider: Error code 0x2749 ...')

考えられる原因と解決策:

  • ホストとして使用されない Docker Compose サービス名

    Docker Compose を使用する場合は、DB_HOSTdbではなく、サービス名 (localhost など) に127.0.0.1を設定します。

  • SQL Server コンテナの準備ができていません

    SQL Server コンテナーの起動には数秒かかります。 ヘルスチェックまたは起動遅延を追加する:

    services:
      db:
        image: mcr.microsoft.com/mssql/server:2022-latest
        healthcheck:
          test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$$MSSQL_SA_PASSWORD" -No -Q "SELECT 1" || exit 1
          # $$ escapes the $ sign in Docker Compose YAML
          interval: 10s
          retries: 10
          start_period: 10s
      web:
        depends_on:
          db:
            condition: service_healthy
    
  • ポートマッピングの競合

    SQL Serverの別のインスタンスがホストで実行されている場合は、公開されているポート (1434:1433 など) を変更し、それに応じて Django 構成を更新します。

Azure SQL一時的なエラー復旧

mssql-django バックエンドは、SERVERPROPERTY('EngineEdition')のクエリを実行して、接続のAzure SQL DatabaseとAzure SQL Managed Instanceを自動的に検出します。 Azure SQLに対して実行すると、バックエンドは一時的なエラー (一時的なリソースの制限や短いネットワークの中断など) で接続を再試行します。

この動作は、 connection_retries オプションと connection_retry_backoff_time OPTIONS を使用して調整できます。

"OPTIONS": {
    "driver": "ODBC Driver 18 for SQL Server",
    "connection_retries": 5,
    "connection_retry_backoff_time": 5,
},

これらの設定は、最初の接続確立にのみ適用されます。 バックエンドは失敗したクエリを再試行しません。 接続が確立された後にクエリが一時的なエラーで失敗した場合、例外はアプリケーション コードに反映されます。 クエリ レベルの回復性には、アプリケーション レベルの再試行ロジック ( django-retry-db やカスタム ミドルウェアなど) を使用します。

低速クエリとプラン回帰

通常、これらの問題には、Django レベルのクエリ レビューと共にサーバー側の分析が必要です。

クエリの速度が低下するか、タイムアウトを開始する

症状:

同じクエリセットが時間の経過と同時に遅くなったり、デプロイ、インデックスの変更、統計の更新後にタイムアウトが開始されたりします。

考えられる原因と解決策:

  • 組み込みのパフォーマンス レポートから始める

    SQL ServerとAzure SQL Managed Instanceの場合は、SQL Server Management Studioでパフォーマンス ダッシュボードを開きます。 Azure SQL Databaseの場合は、Azure SQL Databaseの Query Performance Insight を開きます。 これらのツールは、コストの高いクエリ、待機、リソースの負荷をすばやく表示するため、通常、アドホック DMV クエリよりも優れた最初の手順です。

  • 回帰を計画する

    クエリ ストアを使用して低速クエリを検索し、複数のプランがあるかどうかを確認します。 『クエリ ストア を使用したワークロードの監視のベスト プラクティス』で説明されている 性能が低下したクエリ ビューと 最も多くのリソースを消費するクエリ ビューから始めます。

  • 非効率的な実行プラン

    ステートメントの 実際の実行プラン を開き、テーブルまたはインデックスのスキャン、大きなキー参照、ハッシュスピル、または不正確な行の見積もりを確認します。 背景については、「 実行プランの概要」を参照してください。

  • 間違ったボトルネックが特定されました

    クエリが CPU にバインドされていない場合は、クエリ ストア待機統計を使用し、CPU、メモリ、ディスク I/O、ブロック、接続の負荷を区別するためのボトルネックを特定します。

  • 間違ったレイヤーで適用される修正

    最小の効果的な修正を適用します。インデックスの追加または調整、統計の更新、選択した列と行の削減、大規模な書き込みのバッチ処理などです。 緊急対応策が必要な場合、根本原因を修正しながら、DBA はクエリ ストアで既知の適切な計画を一時的に強制できます。

対話型クエリに dbshell を使用する

Django の dbshell 管理コマンドは、データベースに接続された対話型 SQL シェルを開きます。

python manage.py dbshell

バックエンドは、Microsoft ODBC ドライバーを構成するときにsqlcmdを使用するか、FreeTDS を使用するときにisqlします。 ツールがパス上にあるかどうかを確認します。

  • Windows: sqlcmdはSQL Serverツールに含まれています。または、個別にダウンロードすることもできます。
  • Linux および macOS: Microsoft リポジトリからmssql-tools18をインストールします。