Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O pooling de ligações melhora o desempenho das aplicações ao reutilizar ligações à base de dados em vez de criar novas para cada pedido. Abrir uma ligação envolve vários passos demorados:
- O controlador cria um socket de rede.
- O driver completa o aperto de mão TLS.
- O driver autentica-se com o servidor.
- O driver valida os parâmetros da ligação.
O pooling de ligações mantém as ligações abertas e disponíveis para reutilização, por isso a sua aplicação não precisa de repetir estes passos para cada pedido.
Comportamento padrão
O agrupamento de ligações está ativado por defeito quando cria a sua primeira ligação. As configurações padrão são:
| Setting | Valor predefinido | Descrição |
|---|---|---|
max_size |
100 | Número máximo de ligações por cada cadeia de ligação única. |
idle_timeout |
600 segundos (10 minutos) | Número de segundos antes de as ligações inativas serem fechadas. |
import mssql_python
# Pooling is automatically enabled with defaults
conn = mssql_python.connect(connection_string)
Configurar o agrupamento de conexões
Configure o pooling antes de criar qualquer ligação:
import mssql_python
# Configure custom pool settings
mssql_python.pooling(max_size=50, idle_timeout=300)
# Now create connections
conn = mssql_python.connect(connection_string)
Parameters
A pooling() função aceita os seguintes parâmetros:
| Parâmetro | Tipo | Default | Descrição |
|---|---|---|---|
max_size |
int | 100 | Número máximo de ligações agrupadas por cadeia de ligação. |
idle_timeout |
int | 600 | Segundos antes de as conexões inativas serem removidas do pool. |
enabled |
bool | Verdade | Ativar ou desativar o pooling. |
Desativar o agrupamento de ligações
Para desativar o agrupamento, chame pooling() com enabled=False antes de criar conexões:
import mssql_python
mssql_python.pooling(enabled=False)
# Connections are now created and destroyed per use
conn = mssql_python.connect(connection_string)
Note
Defina a configuração de agrupamento antes de estabelecer qualquer conexão. Chamar pooling() depois de criar ligações não tem efeito.
Como funciona o agrupamento
Isolamento da corda de ligação
Cada cadeia de ligação única mantém o seu próprio pool independente. Os pools não partilham ligações entre diferentes cadeias de ligações:
# These use separate pools
conn1 = mssql_python.connect("Server=<server1>;Database=<database1>;...")
conn2 = mssql_python.connect("Server=<server2>;Database=<database2>;...")
Ciclo de vida da ligação
Obter (estabelecer uma ligação):
- O conjunto remove ligações expiradas por inatividade.
- A piscina tenta reutilizar uma ligação existente:
- Verifica se a ligação está ativa.
- Reinicia o estado da ligação.
- Se ambos os testes tiverem sucesso, a ligação retorna.
- Se não existir nenhuma ligação reutilizável e o pool estiver abaixo de
max_size, o driver cria uma nova ligação. - Se o pool estiver com capacidade máxima e sem ligações válidas, o driver gera um erro.
Libertar (devolver uma conexão):
- Se a piscina tiver capacidade, armazena a ligação para reutilização.
- Se o pool estiver em
max_size, o controlador fecha a conexão imediatamente.
Verificações do estado da ligação
O controlador efetua verificações do estado da ligação antes de voltar a utilizar uma ligação do conjunto.
- Verificação de atividade: Garante que a ligação à rede continua válida.
- Verificação de reset: Reinicia o estado da sessão (nível de isolamento, definições) para uma reutilização limpa.
Se algum dos testes falhar, o pool descarta a ligação e cria uma nova.
Limpeza automática
-
Tempo de espera de inatividade: O driver fecha ligações que não são utilizadas por mais tempo do que o
idle_timeoutvalor. -
Saída do processo: Um
atexitprocessador fecha todas as ligações agrupadas quando o processo Python termina.
Melhores práticas
Dimensione a sua piscina de forma adequada
Ajuste o tamanho do seu grupo com a concorrência da sua aplicação.
# For a web application with 20 concurrent requests
mssql_python.pooling(max_size=25) # Slightly more than expected concurrency
Utilizar gestores de contexto
Os gestores de contexto garantem que as ligações sejam corretamente devolvidas ao pool.
with mssql_python.connect(connection_string) as conn:
cursor = conn.cursor()
cursor.execute("SELECT TOP 5 Name, ListPrice FROM Production.Product")
rows = cursor.fetchall()
# Connection returned to pool
Mantenha as cadeias de ligação consistentes
Parâmetros diferentes nas cadeias de ligação criam pools separados.
# These create THREE separate pools (inefficient)
conn1 = mssql_python.connect("Server=<server>;Database=<database>;Encrypt=yes;")
conn2 = mssql_python.connect("SERVER=<server>;DATABASE=<database>;ENCRYPT=yes;") # Different case
conn3 = mssql_python.connect("Server=<server>;Database=<database>;Encrypt=yes;", timeout=30) # Extra parameter
# Use a constant connection string instead
CONNECTION_STRING = "Server=<server>;Database=<database>;Encrypt=yes;"
conn1 = mssql_python.connect(CONNECTION_STRING)
conn2 = mssql_python.connect(CONNECTION_STRING) # Same pool
Considere os limites de ligação do SQL do Azure
Base de Dados SQL do Azure impõe limites de ligação com base no nível de serviço. Os valores seguintes são aproximados; Consulte a documentação ligada para os limites atuais:
| Escalão de serviço | Máximo de conexões simultâneas |
|---|---|
| Básico | 30 |
| Padrão S0-S2 | 60-120 |
| Standard S3 e versões posteriores | 200 |
| Premium | 500 |
Reduza o valor max_size abaixo destes limites.
# For Azure SQL Standard S2 (120 limit)
mssql_python.pooling(max_size=100) # Leave headroom
Ajuste o tempo limite de inatividade da sua carga de trabalho
-
Ligações frequentes: Use um valor mais longo
idle_timeoutpara manter as ligações quentes. -
Ligações esporádicas: Use um valor mais
idle_timeoutcurto para libertar recursos.
# High-frequency API: keep connections warm
mssql_python.pooling(idle_timeout=1800) # 30 minutes
# Batch job running every hour: release between runs
mssql_python.pooling(idle_timeout=60) # 1 minute
Limitations
A implementação atual tem algumas limitações em comparação com outros drivers:
| Feature | Situação |
|---|---|
ClearPool() / ClearAllPools() |
Não disponível. |
| Estatísticas e monitorização do pool | Não disponível. |
| Override por pool de ligação | Não disponível. |
| Tamanho mínimo da piscina | Não é configurável. |
Exemplo: padrão de aplicação web
O exemplo seguinte do Flask mostra como as ligações são agrupadas de forma transparente entre pedidos:
import mssql_python
from flask import Flask, g
app = Flask(__name__)
# Configure pooling at startup
mssql_python.pooling(max_size=20, idle_timeout=300)
def get_db():
if 'db' not in g:
g.db = mssql_python.connect(app.config['DATABASE_URL'])
return g.db
@app.teardown_appcontext
def close_db(error):
db = g.pop('db', None)
if db is not None:
db.close() # Returns to pool
@app.route('/products')
def list_products():
conn = get_db()
cursor = conn.cursor()
cursor.execute("SELECT TOP 5 Name, ListPrice FROM Production.Product")
return cursor.fetchall()
Reconhecer o cansaço na piscina
Quando todas as ligações da piscina estão em uso e solicita uma nova ligação, observa sintomas como:
- As ligações ficam suspensas ou apagam enquanto se espera por uma ligação gratuita.
- A taxa de processamento da aplicação cai subitamente sob carga.
- O consumo de memória aumenta à medida que o driver cria ligações que não consegue reutilizar.
Causas comuns:
- As ligações não são devolvidas ao pool. Fecha sempre as ligações quando terminares, ou usa gestores de contexto. Uma ligação que não está fechada mantém-se verificada.
- A piscina é demasiado pequena para a carga de trabalho. Se tiver 50 solicitações simultâneas, mas se
max_size=20, 30 solicitações ficam em espera. - Consultas de longa duração mantêm ligações. Divida as operações longas em partes ou use ligações dedicadas para processamento em lote.
Como corrigir:
# 1. Always use context managers to guarantee return
with mssql_python.connect(connection_string) as conn:
cursor = conn.cursor()
cursor.execute("SELECT ...")
rows = cursor.fetchall()
# Connection returned to pool here, even if an exception occurs
# 2. Size the pool to match your concurrency
mssql_python.pooling(max_size=50) # Match or slightly exceed expected concurrent connections
# 3. Reduce idle timeout if connections go stale
mssql_python.pooling(idle_timeout=120)