Gerencie conexões com mssql-python

A maioria das aplicações segue um padrão simples: abrir uma conexão, rodar consultas, fechar a conexão. As seções seguintes abordam a abertura e o fechamento de conexões, uso de gerenciadores de contexto, configuração de autocommit e trabalho com atributos de conexão.

Abra uma conexão

Use a connect() função para estabelecer uma conexão. Passe uma cadeia de conexão com seus dados de servidor, banco de dados e autenticação:

import mssql_python

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;Database=<database>;"
    "Authentication=ActiveDirectoryDefault;Encrypt=yes"
)

A connect() função aceita:

  • Uma cadeia de conexão como o primeiro argumento posicional ou a palavra-chave connection_str.
  • Palavras-chave individuais que o driver mescla na cadeia de caracteres de conexão.
  • Outras opções como autocommit, timeout, e attrs_before.

Você pode misturar as duas abordagens. Palavras-chave substituem valores na cadeia de caracteres de conexão, o que é útil quando você armazena uma cadeia de caracteres de conexão base na configuração e substitui configurações como timeout a cada chamada:

# Base connection string from config, with per-call overrides
conn = mssql_python.connect(
    "Server=<server>.database.windows.net;Database=<database>;"
    "Authentication=ActiveDirectoryDefault;Encrypt=yes",
    timeout=30,
    autocommit=True
)

Feche uma conexão

Sempre feche as conexões quando terminadas para devolvê-las ao pool de conexões e libere os recursos do servidor. Conexões não fechadas armazenam memória do lado do servidor e podem eventualmente esgotar o pool de conexões, causando novas tentativas de bloqueio ou falha.

conn = mssql_python.connect(connection_string)
try:
    # Use the connection
    cursor = conn.cursor()
    cursor.execute("SELECT 1")
finally:
    conn.close()

Uma vez fechada, a conexão não pode ser usada:

conn.close()
print(conn.closed)  # True

# This raises an error
cursor = conn.cursor()  # InterfaceError: Cannot create cursor on closed connection

Chamar close() várias vezes é seguro (idempotente):

conn.close()
conn.close()  # No error

Gerenciadores de contexto

Use a with instrução para gerenciar conexões na maioria das aplicações. Garante que o driver feche a conexão quando o bloco sai, mesmo que ocorra uma exceção. Essa abordagem elimina o risco de vazamento de conexões devido a chamadas close() esquecidas:

with mssql_python.connect(connection_string) as conn:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
    cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
    conn.commit()  # Must commit explicitly when autocommit=False
# Connection automatically closed

O gerenciador de contexto fecha a conexão na saída. Não efetua commit automaticamente nem reverte transações:

  • Sempre: Chama close() na saída, tenha ocorrido uma exceção ou não.
  • close() comportamento: se autocommit=False, quaisquer alterações não comprometidas são revertidas quando a conexão se fecha.
  • Você deve chamar conn.commit() explicitamente para persistir as mudanças.

Esse design segue o comportamento da PEP 249 e evita commits parciais acidentais. Se o seu código lançar uma exceção antes de atingir commit(), a transação em andamento será revertida com segurança:

# Equivalent manual code:
conn = mssql_python.connect(connection_string)
try:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
    cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
    conn.commit()  # Must commit explicitly
finally:
    conn.close()  # Rolls back uncommitted changes if autocommit=False

Modo de confirmação automática

Por padrão, autocommit=False, o que significa que cada instrução é executada dentro de uma transação implícita. Você deve chamar conn.commit() para salvar as alterações ou conn.rollback() para descartá-las. Transações implícitas são a escolha mais segura para modificações de dados porque permitem agrupar múltiplas instruções em uma única operação atômica.

Ative a confirmação automática quando quiser que cada instrução seja efetivada imediatamente. Autocommit é útil para operações DDL (CREATE TABLE, ALTER INDEX), cargas de trabalho de somente leitura ou scripts administrativos em que não é necessário agrupar transações:

conn = mssql_python.connect(connection_string)
print(conn.autocommit)  # False

cursor = conn.cursor()
cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
conn.commit()  # Required to persist changes

Ative a confirmação automática para que cada instrução seja confirmada imediatamente. Use autocommit=True no momento da conexão ou altere essa opção após se conectar com setautocommit() ou por atribuição direta da propriedade:

# At connection time
conn = mssql_python.connect(connection_string, autocommit=True)

# Or after connection (both forms work)
conn.setautocommit(True)
conn.autocommit = True
print(conn.autocommit)  # True

# Now changes are committed automatically
cursor = conn.cursor()
cursor.execute("SELECT TOP 1 Name FROM Production.Product")
print(cursor.fetchone().Name)
# No commit() needed

Tempo de espera da conexão esgotado

Defina o timeout da conexão para controlar quanto tempo o driver espera para estabelecer a conexão antes de gerar um erro. Um tempo de conexão razoável é importante para aplicações implantadas em ambientes com redes pouco confiáveis ou para falhas rápidas quando um servidor está inacessível:

# At connection time (in seconds)
conn = mssql_python.connect(connection_string, timeout=30)

# Or after connection
conn.timeout = 60
print(conn.timeout)  # 60

Um tempo limite de 0 significa nenhum tempo limite (aguarda indefinidamente). Defina tempos limite razoáveis na produção; uma tentativa de conexão travada sem tempo limite bloqueia permanentemente a thread de chamadas.

Se o alvo for Banco de Dados SQL do Azure serverless com autopausa ativada, use pelo menos 60. Um banco de dados pausado automaticamente é retomado na primeira conexão, e a retomada pode levar de 30 a 60 segundos ou mais. Um tempo de espera mais curto expira antes da retomada terminar e a tentativa de conexão falhar.

Atributos de conexão

Use set_attr() para modificar o comportamento da conexão em tempo de execução. Os atributos de conexão controlam configurações de driver de baixo nível, como modo de acesso, isolamento de transações e tamanho do pacote. A maioria das aplicações não precisa alterar esses atributos, mas eles são úteis para cenários específicos:

  • Modo somente leitura: Previne escritas acidentais em consultas de relatórios.
  • Isolamento de transações: Controla como as transações concorrentes interagem (uso SERIALIZABLE para consistência estrita, READ_COMMITTED para uso geral).
  • Tamanho do pacote: Ajuste para redes de alta latência ou alta taxa de transferência.
import mssql_python

conn = mssql_python.connect(connection_string)

# Set read-only mode
conn.set_attr(mssql_python.SQL_ATTR_ACCESS_MODE, mssql_python.SQL_MODE_READ_ONLY)

# Set transaction isolation level
conn.set_attr(mssql_python.SQL_ATTR_TXN_ISOLATION, mssql_python.SQL_TXN_SERIALIZABLE)

Atributos disponíveis:

Constante Descrição
SQL_ATTR_CONNECTION_TIMEOUT Tempo limite de conexão em segundos.
SQL_ATTR_LOGIN_TIMEOUT Tempo limite para login em segundos.
SQL_ATTR_PACKET_SIZE Tamanho do pacote de rede.
SQL_ATTR_ACCESS_MODE Modo somente leitura ou leitura e gravação.
SQL_ATTR_TXN_ISOLATION Nível de isolamento de transações.
SQL_ATTR_CURRENT_CATALOG Nome atual do banco de dados.

Atributos de pré-conexão

Alguns atributos devem ser definidos antes que o driver estabeleça a conexão (por exemplo, o tempo de encerramento de login). Passe-os por attrs_before:

conn = mssql_python.connect(
    connection_string,
    attrs_before={
        mssql_python.SQL_ATTR_LOGIN_TIMEOUT: 30,
        mssql_python.SQL_ATTR_CONNECTION_TIMEOUT: 60,
    }
)

Obter informações de conexão

Use getinfo() para recuperar metadados de drivers e servidores para registro, diagnóstico ou adaptação de comportamento com base nas capacidades do servidor:

conn = mssql_python.connect(connection_string)

# Server information
print(f"Server name: {conn.getinfo(mssql_python.SQL_SERVER_NAME)}")
print(f"Database name: {conn.getinfo(mssql_python.SQL_DATABASE_NAME)}")

# Driver information
print(f"Driver name: {conn.getinfo(mssql_python.SQL_DRIVER_NAME)}")
print(f"Driver version: {conn.getinfo(mssql_python.SQL_DRIVER_VER)}")

Obtenha uma lista de constantes de informação disponíveis:

constants = mssql_python.get_info_constants()
for name, value in constants.items():
    print(f"{name}: {value}")

Caractere de escape de pesquisa

A propriedade searchescape retorna o caractere usado para escapar caracteres curinga (% e _) nos padrões LIKE. Use-o para buscar com segurança caracteres curinga literais na entrada de usuário:

escape = conn.searchescape

# Use in queries with wildcard characters
cursor.execute(
    f"SELECT Name FROM Production.Product WHERE Name LIKE '%{escape}%%' ESCAPE '{escape}'"
)
# Matches names containing literal '%' character

Codificação e decodificação

Configure a codificação de texto para instruções e resultados SQL. As configurações padrão funcionam para a maioria das aplicações. Altere-as apenas se você se conectar a um servidor que use uma codificação diferente de UTF-8 para colunas char/varchar. A codificação que um servidor usa depende da ordenação da coluna:

# Set encoding for outbound text
conn.setencoding(encoding='utf-8')

# Get current encoding settings
settings = conn.getencoding()
print(settings)  # {'encoding': 'utf-8', 'ctype': ...}

# Set decoding for inbound text from specific SQL types
conn.setdecoding(mssql_python.SQL_CHAR, encoding='utf-8')

# Get current decoding settings
settings = conn.getdecoding(mssql_python.SQL_CHAR)
print(settings)

Codificações padrão:

Direção Tipo SQL Codificação padrão
Saída (str) SQL_WCHAR utf-16le
Entrada SQL_CHAR utf-8
Entrada SQL_WCHAR utf-16le
Entrada SQL_WMETADATA utf-16le

Práticas recomendadas

  • Use gerenciadores de contexto (blocos with) para todas as conexões no código da aplicação. Eles garantem a limpeza mesmo quando ocorrem exceções.
  • Use o pool de conexão para melhor desempenho (ativado por padrão). Consulte Sondagem de conexão.
  • Defina tempos limite apropriados para seu ambiente de rede. Um timeout de 30 segundos é adequado para a maioria das implantações em nuvem; aumente para conexões multi-região ou VPN. Use pelo menos 60 para Banco de Dados SQL do Azure serverless com autopausa ativada, porque um banco de dados pausado automaticamente pode levar de 30 a 60 segundos ou mais para retomar na primeira conexão.
  • Defina MultiSubnetFailover=yes na cadeia de conexão quando o destino for Banco de Dados SQL do Azure, Instância Gerenciada de SQL do Azure, banco de dados SQL no Microsoft Fabric, um listener de grupo de disponibilidade ou uma instância de cluster de failover. É seguro em alvos de IP único, então deixe-o ativado para todos os endpoints TCP da família Microsoft SQL.
  • Uso autocommit=False (o padrão) para cenários de modificação de dados onde você precisa de atomicidade transacional.
  • Use autocommit=True para operações DDL, consultas somente de leitura e scripts administrativos.
  • Não compartilhe conexões entre threads. O nível de segurança de thread do driver é 1 (as threads podem compartilhar o módulo, mas não as conexões).