Memecahkan masalah mssql-django

Mendiagnosis dan mengatasi masalah umum pada backend mssql-django untuk SQL Server, Azure SQL Database, Azure SQL Managed Instance, dan database SQL di Microsoft Fabric.

Masalah koneksi

Bagian ini mencakup kesalahan koneksi yang paling umum dan cara mengatasinya.

Driver ODBC tidak ditemukan

Gejala:

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

Or:

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

Kemungkinan penyebab dan solusi:

  • Driver ODBC tidak terinstal

    Instal Driver MICROSOFT ODBC untuk SQL Server. Untuk tautan unduhan, lihat Mengunduh Driver ODBC untuk SQL Server.

  • Beberapa versi driver terinstal

    Tentukan nama atau jalur driver yang tepat di 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",
            },
        },
    }
    

    Di Linux, tentukan jalur lengkap:

    "OPTIONS": {
        "driver": "/opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.10.so.6.1",
    },
    
  • Periksa driver yang terinstal

    • Di Linux/macOS, jalankan odbcinst -q -d.
    • Pada Windows, periksa Sumber Data ODBC di Alat Administratif.

Koneksi ditolak

Gejala:

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

Kemungkinan penyebab dan solusi:

  • TCP/IP tidak diaktifkan pada SQL Server

    • Buka Pengelola Konfigurasi SQL Server.
    • Di bawah Konfigurasi Jaringan SQL Server, aktifkan TCP/IP.
    • Di Properti TCP/IP, aktifkan alamat IP yang digunakan untuk koneksi.
    • Mulai ulang layanan SQL Server.
  • Firewall memblokir port 1433

    • Verifikasi bahwa aturan firewall mengizinkan koneksi masuk pada port 1433.
    • Untuk Azure SQL, tambahkan IP klien Anda di pengaturan firewall portal Azure.
  • Nama atau port server yang salah

    Verifikasi nilai HOST dan PORT dalam konfigurasi Anda.

Gagal masuk

Gejala:

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

Kemungkinan penyebab dan solusi:

  • Kredensial yang salah

    Verifikasi nama pengguna dan kata sandi.

  • Pengguna tidak ada

    Pastikan login dipetakan ke akun pengguna di database target.

  • autentikasi SQL Server dinonaktifkan

    Aktifkan autentikasi mode campuran, atau gunakan autentikasi Windows atau Microsoft Entra.

Waktu koneksi habis

Gejala:

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

Kemungkinan penyebab dan solusi:

  • Latensi jaringan

    Tingkatkan connection_timeout di OPTIONS.

  • Server kelebihan beban

    Tingkatkan connection_retries dan connection_retry_backoff_time.

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

Masalah migrasi

Kesalahan ini terjadi selama operasi migrasi Django terhadap SQL Server.

Masalah tanggal dan waktu

Now() nilai bergeser ketika USE_TZ=True

Gejala:

Tanda waktu yang ditulis dengan Django Now(), , auto_nowatau auto_now_add digeser ketika zona waktu host SQL Server bukan UTC.

Solusi: Tingkatkan ke mssql-django 1.7.2 atau yang lebih baru. Versi 1.7.2 memperbaiki pembuatan SQL yang memperhitungkan Now() zona waktu dan penanganan offset datetimeoffset.

AttributeError saat memanggil .explain()

Gejala:

AttributeError: ... explain_format ...

Solusi: Tingkatkan ke mssql-django 1.7.2 atau yang lebih baru. Versi 1.7.2 memperbaiki kompatibilitas kompilator untuk Django 4.0 dan yang lebih baru menjelaskan metadata.

Tidak dapat mengubah AutoField

Gejala:

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

Solusi: SQL Server tidak mendukung perubahan bidang dari atau ke AutoField. Buat model baru dengan jenis bidang yang diinginkan, migrasikan data secara manual, lalu letakkan tabel lama. Untuk solusinya, lihat Migrasi database dengan mssql-django.

Penggantian nama gagal karena batasan kunci asing

Gejala:

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

Solusi: SQL Server memerlukan penurunan batasan kunci asing sebelum mengganti nama kolom. Gunakan SeparateDatabaseAndState dalam migrasi Anda. Misalnya, lihat Migrasi database dengan mssql-django.

Masalah pengodean

Kesalahan pengodean biasanya terjadi ketika pyodbc salah menafsirkan data karakter dari SQL Server.

Kesalahan pengodean Unicode

Gejala:

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

Solusi: Konfigurasikan pyodbc pengodean dalam OPTIONS kamus:

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

Masalah FreeTDS

FreeTDS memerlukan konfigurasi khusus yang berbeda dari driver ODBC Microsoft.

kesalahan host_is_server

Gejala:

Koneksi gagal saat menggunakan FreeTDS tanpa menentukan host_is_server.

Solusi: Atur host_is_server ke True saat Anda menggunakan FreeTDS:

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

Untuk informasi selengkapnya tentang konfigurasi FreeTDS, lihat Opsi koneksi untuk mssql-django.

Menguji masalah database

Pembuatan dan penghancuran database pengujian dapat gagal tergantung pada metode autentikasi Anda.

Tidak dapat membuat database pengujian dengan identitas terkelola

Gejala:

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

Or:

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

Runner pengujian gagal membuat atau menghapus database pengujian saat Anda menggunakan autentikasi ActiveDirectoryMsi (identitas terkelola). Batasan ini ada karena:

  • Kredensial identitas terkelola diperoleh dari lingkungan host (seperti Azure VM dan App Service).

  • Pelari pengujian mencoba menyambungkan menggunakan kredensial database pengujian selama teardown.

  • Identitas terkelola dapat diberi peran pada tingkat database, tetapi pembuatan dan penghapusan database uji biasanya memerlukan izin tingkat server yang sering kali tidak dimiliki oleh runner pengujian.

Metode autentikasi yang terpengaruh:

  • ActiveDirectoryMsi(Azure identitas terkelola)
  • ActiveDirectoryServicePrincipal (bila hanya dikonfigurasi pada tingkat server)

Metode autentikasi yang didukung (pekerjaan pembuatan database pengujian):

  • ActiveDirectoryPassword
  • ActiveDirectoryIntegrated
  • Autentikasi SQL (nama pengguna/kata sandi)

Kompromi autentikasi untuk lingkungan pengujian

Metode Tanpa rahasia Mendukung pembuatan/penghapusan database pengujian secara otomatis Kegunaan umum
ActiveDirectoryMsi Yes Biasanya tidak (kecuali hak akses tingkat server diberikan) beban kerja produksi yang dihosting di Azure
ActiveDirectoryServicePrincipal Tidak (rahasia/sertifikat klien) Tergantung pada hak tingkat server yang diberikan CI/CD dengan manajemen identitas eksplisit
ActiveDirectoryPassword No Ya (dengan izin SQL yang memadai) Pengembang dan lingkungan CI terkontrol
Autentikasi SQL No Ya (dengan izin SQL yang memadai) Lingkungan pengujian lokal atau terisolasi

Solusi:

  • Untuk pengembangan: Gunakan flag --keepdb untuk melewati pembongkaran database uji:

    python manage.py test --keepdb
    
  • Untuk alur CI/CD: Buat database pengujian khusus sebelumnya dan berikan identitas CREATE TABLE dan ALTER izin terkelola:

    -- 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];
    
  • Alternatif: Gunakan autentikasi SQL untuk lingkungan pengujian, atau beralihlah ke ActiveDirectoryPassword untuk runner pengujian CI/CD.

Prosedur pemulihan

Saat migrasi gagal di tengah proses, gunakan urutan rollback ini untuk kembali ke kondisi stabil yang diketahui:

  1. Hentikan penulisan aplikasi untuk menghindari penyimpangan skema tambahan.

  2. Periksa status migrasi:

    python manage.py showmigrations
    python manage.py sqlmigrate <app_label> <migration_number>
    
  3. Gulung balik ke migrasi baik terakhir yang diketahui:

    python manage.py migrate <app_label> <previous_migration>
    
  4. Jika skema dan riwayat migrasi berbeda, perbaiki status dengan hati-hati menggunakan --fake hanya setelah memverifikasi skema database yang sebenarnya.

  5. Jalankan kembali migrasi di lingkungan penahapan terlebih dahulu, lalu coba lagi produksi.

Important

Untuk migrasi destruktif seperti penghapusan, penggantian nama, dan perubahan tipe kolom, buat cadangan yang telah diuji sebelum penerapan. Jika rollback melalui migrasi tidak memungkinkan, pulihkan dari cadangan dan terapkan kembali migrasi yang telah divalidasi.

Masalah Docker dan kontainer

Gambar kontainer memerlukan penginstalan driver ODBC eksplisit dan membangun dependensi.

Driver ODBC tidak ditemukan dalam kontainer

Gejala:

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

Kemungkinan penyebab dan solusi:

  • Driver ODBC tidak diinstal dalam gambar kontainer

    Image dasar Slim atau Alpine tidak menyertakan driver ODBC. Tambahkan repositori APT Microsoft dan instal msodbcsql18 di Dockerfile Anda. Lihat Menyebarkan ke App Service untuk contoh Dockerfile lengkap.

  • Paket hilang unixodbc-dev

    Roda pyodbc terhubung dengan libodbc.so. Instal unixodbc-dev (Debian/Ubuntu) atau unixODBC-devel (RHEL/Fedora) sebelum menginstal paket Python.

pyodbc gagal dikompilasi pada image slim

Gejala:

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

Or:

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

Solusi: Instal dependensi build sebelum pip install:

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

Atau, gunakan build bertahap untuk menjaga image akhir tetap kecil:

# 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/*

Kontainer tidak dapat tersambung ke SQL Server

Gejala:

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

Kemungkinan penyebab dan solusi:

  • Nama layanan Docker Compose tidak digunakan sebagai host

    Saat menggunakan Docker Compose, atur DB_HOST ke nama layanan (misalnya, db), bukan localhost atau 127.0.0.1.

  • kontainer SQL Server belum siap

    Kontainer SQL Server membutuhkan waktu beberapa detik untuk memulai. Tambahkan pemeriksaan kesehatan atau penundaan startup:

    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
    
  • Konflik pemetaan port

    Jika instans lain SQL Server berjalan pada host, ubah port yang diekspos (misalnya, 1434:1433) dan perbarui konfigurasi Django Anda yang sesuai.

Azure SQL pemulihan kesalahan sementara

Backend mssql-django secara otomatis mendeteksi koneksi Azure SQL Database dan Azure SQL Managed Instance dengan mengkueri SERVERPROPERTY('EngineEdition'). Saat berjalan dengan Azure SQL, sistem backend akan mencoba kembali koneksi saat terjadi error transien (seperti pembatasan sumber daya sementara atau gangguan jaringan singkat).

Anda dapat menyesuaikan perilaku ini dengan opsi connection_retries dan connection_retry_backoff_time:

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

Pengaturan ini hanya berlaku untuk pembentukan koneksi awal. Backend tidak mengulangi kueri yang gagal. Jika kueri gagal dengan kesalahan sementara setelah koneksi dibuat, pengecualian akan disebarluaskan ke kode aplikasi Anda. Gunakan logika coba lagi tingkat aplikasi (misalnya, django-retry-db atau middleware kustom) untuk ketahanan tingkat kueri.

Kueri lambat dan regresi rencana

Masalah ini biasanya memerlukan analisis sisi server bersama dengan tinjauan kueri tingkat Django.

Kueri menjadi lebih lambat atau mulai kehabisan waktu

Gejala:

Set kueri yang sama menjadi lebih lambat dari waktu ke waktu, atau mulai kehabisan waktu setelah pembaruan penyebaran, perubahan indeks, atau statistik.

Kemungkinan penyebab dan solusi:

  • Mulai dengan laporan performa bawaan

    Untuk SQL Server dan Azure SQL Managed Instance, buka Dasbor Performa di SQL Server Management Studio. Untuk Azure SQL Database, buka Query Performance Insight untuk Azure SQL Database. Alat ini biasanya menjadi langkah awal yang lebih baik daripada kueri DMV ad hoc karena dapat dengan cepat mengungkap kueri yang mahal, waktu tunggu, dan tekanan pada sumber daya.

  • Merencanakan regresi

    Gunakan Query Store untuk menemukan kueri yang lambat dan periksa apakah kueri tersebut memiliki beberapa rencana eksekusi. Mulailah dengan tampilan Kueri yang Diregresi dan Kueri Penggunaan Sumber Daya Teratas yang dijelaskan dalam Praktik terbaik untuk memantau beban kerja dengan Query Store.

  • Rencana eksekusi tidak efisien

    Buka rencana eksekusi aktual untuk pernyataan dan periksa pemindaian tabel atau indeks, pencarian kunci besar, tumpahan hash, atau perkiraan baris yang tidak akurat. Untuk latar belakang, lihat Gambaran umum rencana eksekusi.

  • Hambatan yang salah diidentifikasi

    Jika kueri tidak terikat CPU, gunakan statistik tunggu Query Store dan Identifikasi hambatan untuk membedakan CPU, memori, I/O disk, pemblokiran, dan tekanan koneksi.

  • Perbaikan diterapkan di lapisan yang salah

    Terapkan perbaikan paling kecil yang tetap efektif: tambahkan atau sesuaikan indeks, perbarui statistik, kurangi jumlah kolom dan baris yang dipilih, atau lakukan penulisan data besar secara batch. Jika Anda memerlukan mitigasi darurat, DBA dapat untuk sementara memaksakan rencana eksekusi yang telah terbukti baik di dalam Query Store selagi Anda memperbaiki penyebab utamanya.

Menggunakan dbshell untuk kueri interaktif

Perintah manajemen Django dbshell membuka shell SQL interaktif yang tersambung ke database Anda:

python manage.py dbshell

Backend menggunakan sqlcmd saat Anda mengonfigurasi driver MICROSOFT ODBC, atau isql saat Anda menggunakan FreeTDS. Pastikan alat tersebut ada di PATH Anda:

  • Windows: sqlcmd disertakan dengan alat SQL Server, atau Anda dapat mengunduhnya secara terpisah.
  • Linux dan macOS: Instal mssql-tools18 dari repositori Microsoft.