Pooling de conexões do SQL Server com Microsoft.Data.SqlClient

O pool de conexões do Microsoft.Data.SqlClient reutiliza conexões físicas autenticadas. SqlConnection.Open Ou OpenAsync verifica uma piscina para ver se há uma conexão utilizável. Close, Dispose ou DisposeAsync o reiniciam e o retornam. Essa abordagem evita conexão de rede, autenticação e configuração de sessão para cada operação.

O pooling está ativado por padrão. Use este padrão de aplicação:

await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(cancellationToken);

using var command = new SqlCommand(sql, connection);
await command.ExecuteNonQueryAsync(cancellationToken);

Abra até tarde, descarte cedo e deixe a piscina gerenciar as conexões físicas. Não deixe um SqlConnection aberto globalmente.

Entenda as chaves da piscina

Uma conexão só pode ser reutilizada apenas do pool correspondente. A chave do pool inclui mais do que o servidor de destino.

Input Comportamento do pool
string de conexão O texto precisa corresponder exatamente. Diferenças na ordem das palavras-chave criam pools separados, mesmo quando as configurações efetivas são equivalentes.
Autenticação integrada do Windows A identidade do Windows faz parte da chave. A mesma string usada com identidades diferentes cria pools diferentes.
SqlCredential A instância do objeto faz parte da chave. Instâncias separadas criam pools separados mesmo quando contêm o mesmo nome de usuário e senha.
SqlConnection.AccessToken O valor do token de acesso faz parte da chave. Substituir cadeias de tokens pode criar novos pools e deixar conexões autenticadas com tokens antigos em pools existentes.
SqlConnection.AccessTokenCallback O callback faz parte da chave. Reuse a mesma instância de callback para conexões que deveriam compartilhar um pool. O valor do token devolvido não é a chave do pool.
Provedor de contexto SSPI personalizado A instância do provedor participa da configuração da conexão. Reutilize uma instância de provedor para conexões que devem se agrupar.
Transação ambiente Conexões alistadas usam subdivisões específicas de transação dentro do pool correspondente.

O banco de dados, o modo de autenticação, as opções de criptografia, o nome do aplicativo, as opções de pooling e todos os outros valores da string de conexão contribuem por meio da string exata.

Crie uma cadeia de conexão canônica e reutilize-a. Evite valores por requisição em Application Name, Workstation ID, ou outras palavras-chave.

Escolha APIs de token que possam ser agrupadas

Para tokens de acesso do Microsoft Entra ID, use um modo de autenticação fornecido por Microsoft.Data.SqlClient ou um AccessTokenCallback estável.

AccessTokenCallbackfoi introduzido na Microsoft. Data.SqlClient 5.2. O driver o invoca quando precisa de um token e pode solicitar um token renovado para um pool reutilizado. Mantenha o callback determinístico para os parâmetros de autenticação fornecidos pelo driver e reutilize a mesma instância de delegado.

Quando o código define AccessToken diretamente:

  • A string de tokens passa a fazer parte da chave do pool.
  • A aplicação é responsável pela expiração e atualização do token.
  • Uma conexão física agrupada pode sobreviver ao token usado para criá-la.
  • Chame ClearPool após substituir um token expirado se esse pool não puder mais ser usado com segurança.

Não crie uma nova função lambda de callback nem um novo objeto de credenciais a cada solicitação. Diferenças de identidade de objetos podem fragmentar os pools.

Microsoft.Data.SqlClient 7.0 adiciona o SspiContextProvider para negociação personalizada de Kerberos ou NTLM. Trate o provedor como uma configuração de conexão no escopo da aplicação, não como um estado de cada requisição.

Tamanho de cada piscina

Estas opções da cadeia de conexão controlam um pool:

Keyword Padrão Effect
Pooling true Ativa ou desativa o agrupamento.
Min Pool Size 0 Define o número mínimo de conexões físicas que o pool mantém após sua criação.
Max Pool Size 100 Define o número máximo de conexões físicas no pool.
Connect Timeout 15 segundos Define por quanto tempo Open espera quando nenhuma conexão utilizável estiver disponível.
Load Balance Timeout 0 Segundos Descarta uma conexão quando retorna ao pool se sua idade exceder o valor configurado. Connection Lifetime é um alias.

O pool cria conexões conforme a demanda cresce até atingir Max Pool Size. Quando todas as conexões estiverem em uso, as aberturas posteriores aguardam o retorno da conexão. Se a espera exceder Connect Timeout, a abertura falha.

Não eleve Max Pool Size antes de verificar:

  • Cada conexão e leitor está disponível em todos os caminhos.
  • Comandos e transações são concluídos rapidamente.
  • A carga de trabalho da consulta não é bloqueada nem saturada.
  • O limite de conexões com o banco de dados pode suportar Max Pool Size multiplicado por cada pool em cada instância do aplicativo.

Um valor positivo Min Pool Size mantém as conexões abertas durante períodos de inatividade. Use apenas quando as medições justificarem conexões quentes. Geralmente vai contra arquiteturas de escalonamento até zero, auto-pausa sem servidor e arquiteturas de nuvem com capacidade de pico.

Com o padrão Load Balance Timeout=0, a limpeza periódica normalmente remove as conexões não utilizadas acima Min Pool Size após cerca de quatro a oito minutos, ou o pool as remove quando detecta que a conexão do servidor está quebrada. Trate esse intervalo como comportamento de implementação, não como garantia de idle por conexão. O pool não envia uma consulta de validação antes de cada checkout porque essa ida e volta tira grande parte do benefício do pooling.

Gerenciar períodos de bloqueio de autenticação

Após um tempo limite de autenticação ou outra falha de autenticação, o pool pode entrar em um período de bloqueio. Durante esse período, as tentativas abertas correspondentes relançam a exceção original sem realizar outra tentativa de autenticação.

O primeiro período de bloqueio é de cinco segundos. Após mais uma falha, o período dobra para um minuto.

Pool Blocking Period Controla este comportamento:

Value Behavior
Auto Permite o bloqueio para endpoints comuns do SQL Server e o desativa para sufixos reconhecidos de endpoints do SQL do Azure. Um nome DNS personalizado pode não receber o comportamento do Azure.
AlwaysBlock Ativa o período de bloqueio para todos os endpoints.
NeverBlock Desativa o período de bloqueio.

Mantenha Auto, a menos que a estratégia de repetição da aplicação, definida com base em medições, exija uma escolha diferente. Desativar o período de bloqueio pode transformar um problema de credencial, firewall ou queda de energia em uma tempestade de autenticação.

O período de bloqueio é separado da lógica de retentativa configurável. Um provedor de repetição que abre o mesmo pool durante o período de bloqueio recebe a exceção armazenada em cache.

Gerencie o tempo de vida da conexão e a limpeza

O pool elimina automaticamente o pool afetado quando reconhece um erro fatal, como um failover. O pool fecha conexões ociosas e descarta conexões em uso quando são devolvidas.

Use as APIs de limpeza para uma configuração conhecida ou um limite de credenciais:

  • ClearPool limpa o pool associado a uma SqlConnection configuração.
  • ClearAllPools limpa todos os pools do Microsoft.Data.SqlClient no processo ou domínio do aplicativo.

A piscina fecha as conexões ociosas em uma piscina desobstruída. A piscina marca conexões que estão em uso no momento, então elas são descartadas quando devolvidas.

Limpar os pools faz com que aberturas subsequentes efetuem logins físicos. Não o use como manutenção periódica, como um manipulador geral de erros ou como substituto para encerrar conexões.

Load Balance Timeout proporciona uma rotatividade gradual baseada na idade. Use-o quando uma implantação ou um serviço em cluster precisar que conexões físicas antigas sejam desativadas gradualmente. Confirme se o valor escolhido não causa conexões duras excessivas.

Entender transações

Com System.Transactions.Transaction.Current, o padrão, uma conexão aberta dentro de Enlist=true é automaticamente associada a essa transação.

Quando uma conexão associada a uma transação é encerrada, o pool a coloca em uma subdivisão específica da transação. Uma abertura posterior na mesma transação pode reutilizá-la. A conexão física não retorna ao pool geral até que a transação seja concluída.

Transações ambientais longas ou abandonadas podem, portanto:

  • Mantenha as conexões físicas fora do pool geral.
  • Consumir a capacidade do pool após o fechamento da conexão lógica.
  • Mantenha os bloqueios de servidor e o estado das transações ativos.

Mantenha as transações limitadas, complete-as explicitamente e monitore conexões de estase. Defina Enlist=false apenas quando a conexão precisar permanecer fora de uma transação ambiental.

Prevenir a fragmentação do pool

A fragmentação de pools cria muitos pools pequenos em vez de alguns pools reutilizáveis. As causas mais comuns incluem:

  • Diferenças na ordem das palavras-chave ou nos aliases da string de conexão.
  • Uma cadeia de conexão por cliente, usuário, requisição ou banco de dados.
  • Autenticação integrada sob várias identidades do Windows.
  • Novas SqlCredentialinstâncias de retorno de token de acesso ou provedores SSPI por requisição.
  • Tokens de acesso direto que mudam a cada atualização.
  • Nomes de aplicativos de alta cardinalidade ou IDs de estação de trabalho.

Normalize as cadeias de conexão com SqlConnectionStringBuilder e centralize a criação de conexões.

Se a aplicação intencionalmente se conecta a vários bancos de dados ou identidades, inclua o número de pools resultante no planejamento de capacidade. Não execute USE usando um nome de banco de dados não confiável para encerrar os pools. Isolamento de banco de dados, permissões, estado da sessão e comportamento de reset de pool devem permanecer explícitos.

Considere as funções do aplicativo e o estado da sessão

O pool reinicia o estado reutilizável da sessão do SQL Server antes de atribuir uma conexão física a outra conexão lógica. O código da aplicação ainda deve definir qualquer estado de sessão exigido dentro de sua unidade de trabalho.

Os papéis de aplicativo do SQL Server ativados com sp_setapprole não podem ser redefinidos com segurança para pooling comum. Prefira usuários do banco de dados, usuários contidos, funções, segurança em nível de linha ou outro modelo de autorização. Se uma função de aplicativo for inevitável, use um padrão documentado de reversão baseado em cookies ou desative o agrupamento para esse caminho isolado após os testes.

Descarte os leitores de dados, conclua ou reverta transações e não deixe comandos em execução ao fechar a conexão. Não confie que tabelas temporárias ou outro estado de sessão se mantenham entre conexões lógicas.

Use padrões de pooling hospedados na nuvem

Para Serviço de Aplicativo do Azure, Azure Functions, containers, Kubernetes e outros hosts horizontalmente escalados:

  • Calcule as possíveis conexões com o banco de dados considerando todas as instâncias, processos, chaves de pool e réplicas.
  • Use identidade gerenciada ou um callback de token de acesso estável em vez de rotacionar cadeias de tokens nos objetos de conexão.
  • Mantenha Min Pool Size=0, a menos que um requisito medido de inicialização a frio justifique sessões mantidas.
  • Espere que uma nova instância comece com um pool vazio.
  • Mantenha as strings de conexão idênticas entre as instâncias que atendem à mesma carga de trabalho.
  • Limite as tentativas de conexão e as novas tentativas para evitar picos sincronizados de login durante failover ou scale-out.
  • Defina MultiSubnetFailover=true para o SQL do Azure e outros pontos de extremidade TCP com vários endereços compatíveis.

Os pools de conexão são locais ao processo da aplicação. Eles não são compartilhados entre instâncias de aplicação, containers ou hosts.

Diagnosticar o comportamento do pool

Use contadores de diagnóstico do SqlClient para observar:

  • Conexões e desconexões fixas, que representam conexões físicas de servidores.
  • Soft connections e desconexões, que representam a obtenção e a devolução ao pool.
  • Conexões ativas e gratuitas em pool.
  • Grupos e piscinas ativas.
  • Conexões do Stasis.
  • Recuperei conexões onde o código da aplicação não eliminou a conexão lógica.

Correlacione contadores de clientes com sessões do SQL Server, esperas, bloqueios e limites de recursos. Um timeout de pool pode significar vazamento de conexão, consultas lentas, transações bloqueadas, concorrência excessiva, fragmentação do pool ou limite de capacidade de banco de dados.

Use rastreamento da origem de eventos para rastreamentos específicos do pooler. O rastreamento é verboso. Ative-o para uma janela de diagnóstico limitada e proteja quaisquer metadados de conexão capturados.

Lista de verificação de produção

  • Mantenha o pooling ativado.
  • Reutilize uma cadeia de conexão canônica por carga de trabalho e banco de dados.
  • Elimine conexões, comandos, leitores e transações em todos os caminhos.
  • Reutilize credenciais, chamadas de token e instâncias de provedores SSPI.
  • Defina tempos limite de conexão e de comando.
  • Dimensione o orçamento total de conexão em cada instância de aplicação.
  • Monitore conexões físicas, contagem de conexões no pool, conexões disponíveis, inatividade e timeouts.
  • Limpe os pools apenas no caso de uma credencial, um token ou uma alteração de configuração que o provedor não possa detectar, ou quando os diagnósticos confirmarem que ainda existem conexões obsoletas.
  • Teste a escalabilidade horizontal, o failover e o comportamento da atualização de credenciais antes da entrada em produção.