Resolução de problemas de mssql-django

Diagnostice e resolva problemas comuns no mssql-django backend do SQL Server, Base de Dados SQL do Azure, Azure SQL Managed Instance e base de dados SQL no Microsoft Fabric.

Problemas de conexão

Esta secção aborda os erros de ligação mais comuns e como resolvê-los.

Controlador ODBC não encontrado

Sintomas:

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'")

Possíveis causas e soluções:

  • Driver ODBC não instalado

    Instale o driver Microsoft ODBC para SQL Server. Para links de download, consulte Download ODBC Driver for SQL Server.

  • Múltiplas versões de drivers instaladas

    Especifique o nome exato do controlador ou o caminho em 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",
            },
        },
    }
    

    No Linux, especifique o caminho completo:

    "OPTIONS": {
        "driver": "/opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.10.so.6.1",
    },
    
  • Verifique os drivers instalados

    • Em Linux/macOS, execute odbcinst -q -d.
    • No sistema Windows, consulte Fontes de Dados ODBC em Ferramentas Administrativas.

Ligação recusada

Sintomas:

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

Possíveis causas e soluções:

  • TCP/IP não ativado no SQL Server

    • Abra o Gestor de Configuração do SQL Server.
    • Em SQL Server Network Configuration, ative TCP/IP.
    • Em TCP/Propriedades IP, ative o endereço IP utilizado para a ligação.
    • Reinicie o serviço SQL Server.
  • Firewall a bloquear a porta 1433

    • Verifica se as regras do firewall permitem ligações de entrada na porta 1433.
    • Para SQL do Azure, adicione o IP do seu cliente nas definições do firewall do portal Azure.
  • Nome de servidor ou porta errados

    Verifica os valores HOST e PORT na configuração.

Início de sessão falhado

Sintomas:

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

Possíveis causas e soluções:

  • Credenciais incorretas

    Verifica o nome de utilizador e a palavra-passe.

  • Utilizador não existe

    Confirme que o login está mapeado para um utilizador na base de dados de destino.

  • Autenticação do SQL Server desativada

    Ative a autenticação em modo misto ou utilize a autenticação Windows ou Microsoft Entra.

Tempo limite de ligação

Sintomas:

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

Possíveis causas e soluções:

  • Latência da rede

    Aumente connection_timeout em OPTIONS.

  • Servidor sobrecarregado

    Aumente connection_retries e connection_retry_backoff_time.

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

Questões relacionadas com a migração

Estes erros ocorrem durante as operações de migração do Django contra o SQL Server.

Questões de data e hora

Now() os valores são deslocados quando USE_TZ=True

Sintomas:

Carimbos temporais escritos com DjangoNow(), auto_now, ou auto_now_add são deslocados quando o fuso horário do host do SQL Server não é UTC.

Solução: Atualizar para mssql-django a 1.7.2 ou posterior. A versão 1.7.2 corrige a geração de SQL Now() com reconhecimento de fuso horário e o tratamento do offset de datetimeoffset.

AttributeError ao chamar .explain()

Sintomas:

AttributeError: ... explain_format ...

Solução: Atualizar para mssql-django a 1.7.2 ou posterior. A versão 1.7.2 corrige a compatibilidade do compilador para Django 4.0 e explica metadados posteriores.

Não é possível alterar o AutoField

Sintomas:

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

Solução: O SQL Server não suporta alterar um campo de ou para AutoField. Crie um novo modelo com o tipo de campo desejado, migre os dados manualmente e depois retire a tabela antiga. Para soluções alternativas, veja Migrações de bases de dados com mssql-django.

Não é possível mudar o nome devido a uma restrição de chave estrangeira

Sintomas:

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

Solução: O SQL Server exige eliminar restrições de chave estrangeira antes de renomear as colunas. Use SeparateDatabaseAndState na sua migração. Para um exemplo, veja Migrações de bases de dados com mssql-django.

Problemas de codificação

Os erros de codificação ocorrem normalmente quando pyodbc interpreta incorretamente os dados de carateres do SQL Server.

Erros de codificação Unicode

Sintomas:

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

Solução: Configurar a codificação pyodbc no dicionário OPTIONS:

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

Problemas do FreeTDS

O FreeTDS requer uma configuração específica que difere do driver ODBC da Microsoft.

host_is_server erro

Sintomas:

A ligação falha ao usar FreeTDS sem especificar host_is_server.

Solução: Defina host_is_server como True quando utilizar o FreeTDS:

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

Para mais informações sobre a configuração do FreeTDS, consulte Opções de ligação para mssql-django.

Problemas com bases de dados de testes

A criação e destruição de bases de dados de teste pode falhar dependendo do seu método de autenticação.

Não é possível criar uma base de dados de teste com identidade gerida

Sintomas:

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

Or:

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

O executor de testes não consegue criar nem destruir a base de dados de teste quando usa a autenticação ActiveDirectoryMsi (identidade gerida). Esta limitação existe porque:

  • As credenciais de identidade gerida são obtidas a partir do ambiente anfitrião (como Azure VM e App Service).

  • O executor de testes tenta estabelecer ligação usando as credenciais da base de dados de teste durante a fase de desmontagem.

  • A identidade gerida pode receber funções ao nível da base de dados, mas a criação e eliminação de bases de dados de teste normalmente requerem permissões a nível de servidor que os executores de testes muitas vezes não têm.

Métodos de autenticação afetados:

  • ActiveDirectoryMsi(Identidade gerida do Azure)
  • ActiveDirectoryServicePrincipal (quando configurado apenas no âmbito do servidor)

Métodos de autenticação suportados (testes de criação de bases de dados):

  • ActiveDirectoryPassword
  • ActiveDirectoryIntegrated
  • Autenticação SQL (nome de utilizador/palavra-passe)

Compensações na autenticação para ambientes de teste

Method Sem segredo Funciona com a criação e eliminação automáticas da base de dados de teste Uso típico
ActiveDirectoryMsi Yes Normalmente não (a menos que sejam concedidos direitos ao nível do servidor) Cargas de trabalho de produção alojadas no Azure
ActiveDirectoryServicePrincipal Não (segredo do cliente/certificado) Depende dos direitos concedidos ao nível do servidor CI/CD com gestão explícita de identidade
ActiveDirectoryPassword No Sim (com permissões SQL suficientes) Ambientes de CI de desenvolvimento e controlados
Autenticação do SQL No Sim (com permissões SQL suficientes) Ambientes de teste locais ou isolados

Soluções:

  • Para desenvolvimento: Use a opção --keepdb para ignorar a eliminação da base de dados de teste:

    python manage.py test --keepdb
    
  • Para pipelines de CI/CD: Criar previamente uma base de dados de teste dedicada e conceder à identidade gerida as permissões CREATE TABLE e ALTER:

    -- 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];
    
  • Alternativa: Utilize a autenticação SQL para ambientes de teste ou mude para ActiveDirectoryPassword para executores de testes de CI/CD.

Procedimentos de reversão

Quando uma migração falhar a meio do processo, utilize esta sequência de reversão para regressar a um estado válido conhecido:

  1. Interrompa as operações de escrita da aplicação para evitar mais divergências no esquema.

  2. Inspecionar o estado da migração:

    python manage.py showmigrations
    python manage.py sqlmigrate <app_label> <migration_number>
    
  3. Reverter para a última migração válida conhecida:

    python manage.py migrate <app_label> <previous_migration>
    
  4. Se o esquema e o histórico de migração divergirem, repare cuidadosamente o estado com --fake só depois de verificar o esquema real da base de dados.

  5. Reexecute as migrações num ambiente de staging primeiro, depois tente novamente a produção.

Importante

Para migrações destrutivas, como eliminação, renomeação e alterações do tipo de coluna, faça uma cópia de segurança testada antes da implementação. Se a reversão por migração não for possível, restaure a partir do backup e reaplique as migrações validadas.

Problemas com dockers e contentores

As imagens de contentores requerem a instalação explícita do controlador ODBC e as dependências de compilação.

Controlador ODBC não encontrado no contentor

Sintomas:

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

Possíveis causas e soluções:

  • Driver ODBC não instalado na imagem do contentor

    As imagens base Slim ou Alpine não incluem o controlador ODBC. Adiciona o repositório Microsoft APT e instala msodbcsql18 no teu Dockerfile. Consulte Deploy to App Service para um exemplo completo do Dockerfile.

  • Pacote em falta unixodbc-dev

    A pyodbc roda liga-se contra libodbc.so. Instale unixodbc-dev (Debian/Ubuntu) ou unixODBC-devel (RHEL/Fedora) antes de instalar pacotes em Python.

O pyodbc não consegue desenvolver imagens finas

Sintomas:

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

Or:

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

Solução: Instalar dependências de compilação antes de pip install

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

Alternativamente, use uma construção em múltiplas fases para manter a imagem final pequena:

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

O contentor não consegue ligar-se ao SQL Server

Sintomas:

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

Possíveis causas e soluções:

  • Nome do serviço do Docker Compose não é usado como host

    Ao usar o Docker Compose, defina DB_HOST para o nome do serviço (por exemplo, db), not localhost ou 127.0.0.1.

  • Contentor SQL Server não pronto

    O contentor do SQL Server demora vários segundos a arrancar. Adicione um exame de saúde ou atraso no arranque:

    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
    
  • Conflitos de mapeamento de portas

    Se outra instância de SQL Server estiver a correr no host, altera a porta exposta (por exemplo, 1434:1433) e atualiza a configuração do Django em conformidade.

SQL do Azure recuperação de erros transitórios

O mssql-django back-end deteta automaticamente as ligações ao Base de Dados SQL do Azure e ao Azure SQL Managed Instance consultando SERVERPROPERTY('EngineEdition'). Ao correr contra SQL do Azure, o backend tenta novamente ligações em erro transitório (como limites temporários de recursos ou breves interrupções de rede).

Pode ajustar este comportamento com as connection_retries e connection_retry_backoff_time OPÇÕES:

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

Estas definições aplicam-se apenas ao estabelecimento inicial da ligação. O backend não tenta novamente as consultas que falharam. Se uma consulta falhar com um erro transitório após a ligação estar estabelecida, a exceção propaga-se para o código da sua aplicação. Utilize lógica de repetição ao nível da aplicação (por exemplo, django-retry-db ou middleware personalizado) para resiliência ao nível das consultas.

Consultas lentas e regressões de planos

Estes problemas normalmente requerem análise do lado do servidor juntamente com revisão de consultas ao nível do Django.

A consulta fica mais lenta ou começa a expirar

Sintomas:

O mesmo conjunto de consultas torna-se mais lento com o tempo, ou começa a expirar após uma implementação, alteração de índice ou atualização de estatísticas.

Possíveis causas e soluções:

  • Comece com relatórios de desempenho incorporados

    Para SQL Server e Azure SQL Managed Instance, abra o Performance Dashboard no SQL Server Management Studio. Para Base de Dados SQL do Azure, abra Query Performance Insight for Base de Dados SQL do Azure. Estas ferramentas são geralmente um melhor primeiro passo do que as consultas ad hoc no DMV, pois rapidamente revelam consultas dispendiosas, esperas e pressão de recursos.

  • Regressão do plano

    Utilize a Query Store para encontrar a consulta lenta e verificar se tem múltiplos planos. Comece pelas vistas de Consultas Regressadas e Consultas que Consomem Mais Recursos descritas nas Melhores Práticas para monitorizar cargas de trabalho com a Query Store.

  • Plano de execução ineficiente

    Abra um plano de execução real da instrução e verifique se há varrimentos de tabelas ou de índices, pesquisas de chave dispendiosas, derramamentos de hash ou estimativas de linhas imprecisas. Para contextualizar, veja Visão geral do plano de execução.

  • Gargalo errado identificado

    Se a consulta não estiver dependente da CPU, utilize as estatísticas de espera do Query Store e Identificar estrangulamentos para distinguir entre problemas de CPU, memória, E/S do disco, bloqueios e sobrecarga de ligações.

  • Correção aplicada na camada errada

    Aplique a correção eficaz mínima: adicione ou ajuste índices, atualize estatísticas, reduza o número de colunas e linhas selecionadas ou agrupe operações de escrita de grande volume em lotes. Se precisar de uma mitigação de emergência, um DBA pode forçar temporariamente um plano, já conhecido por ser bom, no Query Store enquanto corrige a causa raiz.

Utilize dbshell para consultas interativas

O comando de gestão do dbshell Django abre um shell SQL interativo ligado à sua base de dados:

python manage.py dbshell

O backend utiliza sqlcmd quando configura o controlador ODBC da Microsoft, ou isql quando utiliza o FreeTDS. Verifica se a ferramenta está no teu PATH:

  • Windows: sqlcmd está incluído com as ferramentas do SQL Server, ou pode descarregá-lo separadamente.
  • Linux e macOS: Instalar mssql-tools18 a partir do repositório da Microsoft.