Por que estou recebendo o erro “FATAL: remaining connection slots are reserved for non replicate superuser connections” ao me conectar ao meu Amazon RDS para PostgreSQL, mesmo não tendo atingido o limite de max_connections?

6 minuto de leitura
0

Estou recebendo o erro “FATAL: remaining connection slots are reserved for non replicate superuser connections" quando me conecto ao Amazon Relational Database Service (Amazon RDS) para PostgreSQL, embora não tenha atingido o limite de max_connections.

Breve descrição

No Amazon RDS para PostgreSQL, o número máximo real de conexões disponíveis para não superusuários é calculado da seguinte forma:

max_connections - superuser_reserved_connections - rds.rds_superuser_reserved_connections.

O valor padrão para superuser_reserved_connections é 3, e o valor padrão para rds.rds_superuser_reserved_connections é 2.

Por exemplo, se você definir o valor de max_connections como 100, o número real de conexões disponíveis para um não superusuário será calculado da seguinte forma:

100 - 3 - 2 = 95.

A métrica DatabaseConnections do Amazon CloudWatch indica o número de conexões de rede do cliente com a instância do banco de dados no nível do sistema operacional. Essa métrica é calculada medindo-se o número real de conexões TCP com a instância na porta 5432. O número de sessões de banco de dados pode ser maior que esse valor de métrica, pois este último não inclui o seguinte:

  • Processos de back-end que não têm mais uma conexão de rede, mas não são limpos pelo banco de dados. Por exemplo: a conexão é encerrada devido a problemas de rede, mas o banco de dados não fica ciente até tentar retornar a saída para o cliente.
  • Processos de back-end criados pelo agendador de tarefas do mecanismo de banco de dados. Por exemplo: pg_cron.
  • Conexões do Amazon RDS.

Você pode receber esse erro porque a aplicação que se conecta à instância do RDS para PostgreSQL cria e descarta conexões abruptamente. Isso pode fazer com que a conexão de back-end permaneça aberta por algum tempo. Essa condição pode criar uma discrepância entre os valores da exibição pg_stat_activity e a métrica do CloudWatch DatabaseConnections.

Resolução

Solucionar o erro

Para solucionar esse erro, faça as seguintes verificações:

  • Analise a métrica do CloudWatch DatabaseConnections.
  • Use o Performance Insights para visualizar a métrica de contador numbackends. Esse valor fornece informações sobre o número de conexões no momento em que o erro ocorreu. Se você não ativou o Performance Insights, faça login na sua instância como usuário principal. Em seguida, visualize o número de back-ends executando a seguinte consulta:
SELECT count(*) FROM pg_stat_activity;

Se você encontrar algumas conexões ociosas que podem ser encerradas, poderá encerrar esses back-ends usando a função pg_terminate_backend(). É possível exibir todas as conexões ociosas que você deseja encerrar executando a seguinte consulta. Essa consulta exibe informações sobre processos de back-end com um dos seguintes estados por mais de 15 minutos: 'ocioso', 'ocioso na transação', 'ocioso na transação (abortado) 'e 'desabilitado'.

SELECT * FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
AND state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND state_change < current_timestamp - INTERVAL '15' MINUTE;

Observação: certifique-se de atualizar a consulta de acordo com seu caso de uso.

Depois de identificar todos os processos de back-end que devem ser encerrados, encerre esses processos executando a consulta a seguir.

Observação: esta consulta de exemplo encerra todos os processos de back-end em um dos estados mencionados anteriormente por mais de 15 minutos.

SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
AND state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND state_change < current_timestamp - INTERVAL '15' MINUTE
AND usename != 'rdsadmin';

Para encerrar todos os processos de backend ociosos, execute a seguinte consulta:

SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
AND state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND usename != 'rdsadmin';

Observação: não é possível encerrar processos de backend criados com rdsadmin. Portanto, você deve excluí-los do encerramento.

Importante: se você não conseguir se conectar à sua instância do RDS para PostgreSQL com os privilégios rds_superuser, considere fechar seu aplicativo normalmente para liberar algumas conexões.

Gerenciar o número de conexões de banco de dados

Usar o agrupamento de conexões

Na maioria dos casos, é possível usar um grupo de conexões, como um RDS Proxy ou qualquer grupo de conexão de terceiros, para gerenciar o número de conexões abertas em um determinado momento. Por exemplo, se você definir o valor max_connections da instância do RDS para PostgreSQL como 500, poderá evitar erros relacionados a max_connection tendo um grupo de conexões configurado para um máximo de 400 conexões.

Aumentar o valor de max_connections

Você pode considerar aumentar o valor de max_connections dependendo do seu caso de uso. No entanto, definir um valor muito alto para max_connections pode resultar em problemas de memória com base na workload e na classe da instância do banco de dados.

Observação: se você aumentar o valor de max_connections, deverá reinicializar a instância para que a alteração entre em vigor.

Encerrar conexões ociosas

Você pode definir o parâmetro idle_in_transaction_session_timeout como um valor apropriado para o seu caso de uso. Qualquer sessão que esteja ociosa em uma transação aberta por mais tempo do que o especificado nesse parâmetro será encerrada. Por exemplo, se você definir esse parâmetro como 10 minutos, qualquer consulta que estiver ociosa na transação por mais de 10 minutos será encerrada. Esse parâmetro ajuda no gerenciamento de conexões que estão presas nesse estado específico.

Para as versões 14 e posteriores do PostgreSQL, é possível usar o parâmetro idle_session_timeout. Após a definição desse parâmetro, qualquer sessão que estiver ociosa por mais do que o tempo especificado, mas não dentro de uma transação aberta, será encerrada.

Para as versões 14 e posteriores do PostgreSQL, é possível usar o parâmetro client_connection_check_interval. Com esse parâmetro, você pode definir o intervalo de tempo entre verificações opcionais de conexões do cliente ao executar consultas. A verificação é realizada por meio da sondagem do soquete. Ela permite que consultas de longa duração sejam encerradas mais cedo se o kernel informar que a conexão foi fechada. Esse parâmetro ajuda em situações em que o PostgreSQL não sabe sobre a conexão perdida com um processo de back-end.

Aumentar o valor de rds.rds_superuser_reserved_connections

Você pode considerar aumentar o valor do parâmetro rds.rds_superuser_reserved_connections. O valor padrão desse parâmetro é definido como 2. Aumentá-lo permite mais conexões de usuários com a função rds_superuser anexada. Com essa função, os usuários podem executar tarefas administrativas, como encerrar uma conexão ociosa usando o comando pg_terminate_backend().