Files
archived-doc-pt-br/features/persistent-connections.xml
Leonardo Lara Rodrigues 2feb4ef2ac sync with en rev
2025-11-11 15:50:25 -03:00

234 lines
11 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: cd8b964b8566801265f0d287db6eb651f93be950 Maintainer: leonardolara Status: ready --><!-- CREDITS: williancarminato,narigone,ae,leonardolara -->
<chapter xml:id="features.persistent-connections" xmlns="http://docbook.org/ns/docbook">
<title>Conexões Persistentes com o Banco de Dados</title>
<simplesect>
<title>O que são Conexões Persistentes?</title>
<simpara>
Conexões persistentes são conexões que não fecham quando a
execução do seu script termina. Quando uma conexão persistente é
requisitada, o PHP verifica se já existe uma conexão persistente
idêntica (que foi mantida aberta anteriormente) - e, se ela existir, ele
a usa. Se ela não existir, ele cria a conexão. Uma conexão
'idêntica' é uma conexão que foi aberta para o mesmo host, com o
mesmo nome de usuário e a mesma senha (onde for aplicável).
</simpara>
<simpara>
Não há nenhum método para solicitar uma conexão específica ou garantir
se será obtida uma conexão existente ou uma nova (se todas as conexões existentes
estiverem em uso ou se a solicitação estiver sendo atendida por um trabalhador diferente,
que tenha um conjunto separado de conexões).
</simpara>
<simpara>
Isso significa que não se pode usar conexões persistentes do PHP para, por exemplo:
</simpara>
<simplelist>
<member>atribuir uma sessão de banco de dados específica a um usuário da web específico</member>
<member>criar uma grande transação em várias solicitações</member>
<member>iniciar uma consulta em uma solicitação e coletar os resultados em outra</member>
</simplelist>
<simpara>
Conexões persistentes não oferecem <emphasis>nenhuma</emphasis>
funcionalidade que não seria possível com conexões não persistentes.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.web">
<title>Solicitações da Web</title>
<simpara>
Existem duas maneiras pelas quais um servidor web pode utilizar o PHP para gerar
páginas web:
</simpara>
<simpara>
O primeiro método é usar o PHP como um CGI "wrapper". Quando executado dessa
maneira, uma instância do interpretador do PHP é criada e destruída
para cada requisição de página (para uma página PHP) para o seu servidor web.
Como ela é destruída após cada requisição, quaisquer recursos que ela
adquirir (como uma conexão para um servidor de banco de dados SQL) são fechados quando
ela é destruída. Nesse caso, você não ganha nada por tentar
usar conexões persistentes - elas simplesmente não persistem.
</simpara>
<simpara>
O segundo método, e o mais popular, é rodar o PHP-FPM ou o PHP como um módulo
em um servidor web com multi-processos, que atualmente só inclui o Apache.
Essas configurações têm tipicamnente um processo (o pai) que
coordena uma série de processos (seus filhos) que realmente fazem
o trabalho de servir as páginas web. Quando uma requisição chega de um
cliente, ela é entregue à um dos filhos que já não estiver
servindo outro cliente. Isso significa que quando o mesmo cliente
faz uma segunda requisição para o servidor, ele pode ser atendido por um processo
filho diferente do que da primeira vez. Ao abrir uma conexão persistente,
cada página que requisitar serviços de SQL pode reutilizar a mesma
conexão estabelecida ao servidor SQL.
</simpara>
<note>
<para>
Pode-se verificar qual método as solicitações web usam verificando o valor de
"Server API" na saída de <function>phpinfo</function> ou o valor de
<constant>PHP_SAPI</constant>, executado a partir de uma solicitação web.
</para>
<para>
Se a API do Servidor for "Apache 2 Handler" ou "FPM/FastCGI", as conexões
persistentes serão usadas em todas as solicitações atendidas pelo mesmo trabalhador. Para qualquer
outro valor, as conexões persistentes não persistirão após cada solicitação.
</para>
</note>
</simplesect>
<simplesect xml:id="persistent-connections.cli">
<title>Command-line Processes</title>
<simpara>
Como a linha de comando PHP usa um novo processo para cada script, conexões persistentes
não são compartilhadas entre scripts de linha de comando, portanto, não há
nenhum valor em usá-las em scripts transitórios, como crons ou comandos.
No entanto, elas podem ser úteis se, por exemplo, você estiver escrevendo um servidor de aplicativos
de longa duração que atende a muitas solicitações ou tarefas e cada uma pode precisar
de sua própria conexão com o banco de dados.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.why">
<title>Por que usá-las?</title>
<simpara>
Conexões persistentes são boas se a sobrecarga para criar uma conexão ao
servidor SQL for alta. Se essa sobrecarga é realmente alta ou não depende
de vários fatores: o tipo de banco de dados, se está ou não
na mesma máquina do servidor web, o quão carregada
está a máquina do servidor SQL e assim por diante. O
ponto é que se a sobrecarga de conexão for alta, conexões
persistentes ajudam consideravelmente. Elas fazem com que os processos filhos
simplesmente se conectem uma vez só durante toda sua duração, ao invés de
cada vez que eles processam uma página que requer uma conexão ao servidor
SQL. Isso significa que cada filho que abriu uma conexão
persistente terá sua própria conexão persistente para o
servidor. Por exemplo, se você tivesse 20 processos filhos diferentes que
rodassem um script que fizesse uma conexão persistente à um servidor SQL,
você teria 20 conexões diferentes servidor SQL, uma para
cada filho.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.drawbacks.conn-limits">
<title>Possíveis desvantagens: limites de conexão</title>
<simpara>
Perceba, no entanto, que isso pode ter algumas desvantagens se você estiver
usando um banco de dados com limite de conexões que são excedidas pela conexões
persistentes dos filhos. Se o seu banco de dados tem um limite de 16 conexões
simultâneas, e durante um momento de pico de acessos, 17 processos
filhos tentarem se conectar, um deles não será capaz. Se houver
bugs no seus scripts que não permitem que as conexões se fechem
(como loops infinitos) o banco de dados com apenas 16 conexões
pode rapidamente ficar sobrecarregado.
</simpara>
<simpara>
Conexões persistentes geralmente aumentam o número de conexões abertas
a qualquer momento, pois os trabalhadores ociosos ainda manterão as conexões
para as solicitações anteriores que atenderam. Se um grande número de trabalhadores for criado para
lidar com um fluxo de solicitações, as conexões que eles abriram permanecerão até
que o trabalhador seja encerrado ou o servidor de banco de dados feche a conexão.
</simpara>
<simpara>
Certifique-se de que o número máximo de conexões permitidas pelo servidor de banco de dados
seja maior que o número máximo de trabalhadores de solicitação da web (além de qualquer outro
uso, como crons ou conexões administrativas).
</simpara>
<simpara>
Consulte a documentação do banco de dados para obter informações sobre como lidar com conexões abandonadas ou
ociosas (tempo limite). Tempo limite longo pode aumentar significativamente o
número de conexões persistentes abertas ao mesmo tempo.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.drawbacks.state">
<title>Possíveis desvantagens: manter o estado de conexão</title>
<simpara>
Algumas extensões de banco de dados realizam limpeza automática quando a conexão é
reutilizada; outras deixam essa tarefa a critério do desenvolvedor da aplicação.
Dependendo da extensão de banco de dados escolhida e do projeto da aplicação, a limpeza
manual pode ser necessária antes da saída do script. Alterações que podem deixar
conexões em um estado inesperado incluem:
</simpara>
<simplelist>
<member>Banco de dados selecionado / padrão</member>
<member>Bloqueio de tabelas</member>
<member>Transações não confirmadas</member>
<member>Tabelas temporárias</member>
<member>Configurações ou recursos específicos de conexão, como perfilagem</member>
</simplelist>
<simpara>
Bloqueios de tabela e transações que não são limpos ou fechados podem fazer com que
outras consultas sejam bloqueadas indefinidamente e/ou causar a reutilização subsequente
da conexão, causando alterações inesperadas.
</simpara>
<simpara>
Selecionar o banco de dados errado fará com que a reutilização subsequente da
conexão não consiga executar as consultas conforme o esperado (ou executá-las no
banco de dados errado se os esquemas forem semelhantes o suficiente).
</simpara>
<simpara>
Se as tabelas temporárias não forem limpas, as solicitações subsequentes não conseguirão
recriar a mesma tabela.
</simpara>
<simpara>
Pode-se implementar a limpeza usando destruidores de classe ou
<function>register_shutdown_function</function>. Podem ser considerados também
proxies de grupo de conexão dedicados que incluam isso como parte de
sua funcionalidade.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.final-words">
<title>Palavras Finais</title>
<simpara>
Considerando seu comportamento e as potenciais desvantagens descritas acima, não se deve
usar conexões persistentes sem uma análise cuidadosa. Elas não devem ser
usadas sem implementar alterações adicionais em sua aplicação ou sem um configuração cuidadosa
do servidor de banco de dados e servidor web e/ou PHP-FPM.
</simpara>
<simpara>
Considere soluções alternativas, como investigar e corrigir as causas de
sobrecargas na criação de conexões (por exemplo, desabilitando pesquisas reversas de DNS no
servidor de banco de dados) ou proxies de grupo de conexões dedicados.
</simpara>
<simpara>
Para APIs da web de alto volume, considere usar tempos de execução alternativos ou servidores de
aplicações de longa execução.
</simpara>
</simplesect>
<simplesect role="seealso" xml:id="persistent-connections.seealso">
&reftitle.seealso;
<simplelist>
<member><function>ibase_pconnect</function></member>
<member><function>oci_pconnect</function></member>
<member><function>odbc_pconnect</function></member>
<member><function>pfsockopen</function></member>
<member><function>pg_connect</function></member>
<member><link linkend="mysqli.persistconns">MySQLi e Conexões Persistentes</link></member>
<member><link linkend="pdo.connections">Gerenciamento de Conexões PDO</link></member>
</simplelist>
</simplesect>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->