Conexões Persistentes com o Banco de Dados
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).
Pessoas que não são totalmente familiarizadas com a maneira como servidores
web trabalham e distribuem a carga podem confundir conexões persistentes com o que
elas não são. Em particular, elas não dão a
você a capacidade de abrir 'sessões de usuários' na mesma conexão, elas
não dão a você a capacidade de construir uma
transação eficientemente, e elas não fazem muitas outras
coisas. De fato, para ser extremamente claro sobre o assunto,
conexões persistentes não te dão nenhuma
funcionalidade que não era possível com as suas correspondentes
não-persistentes.
Por que?
Isso tem a ver com a maneira como os servidores web funcionam. Existem três maneiras
em que seu servidor web pode utilizar PHP para gerar páginas.
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.
O segundo método, e mais popular, é rodar o PHP como um módulo em um
servidor com multi-processos, que atualmente só inclui o Apache. Um
servidor com multi-processos tipicamente tem 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.
O último método é usar o PHP como um plug-in para um servidor web
multithread. Atualmente, o PHP tem suporte para ISAPI, WSAPI, e NSAPI (no
Windows), todos permitindo PHP ser usado como um plug-in em servidores
multithreaded como Netscape FastTrack (iPlanet), Internet Information Server
(IIS) da Microsoft, e O'Reilly's WebSite Pro. O comportamento é essencialmente
o mesmo do modelo multiprocessado descrito anteriormente.
Se conexões persistentes não tem nenhuma funcionalidade a mais, para
que elas servem?
A resposta é extremamente simples: eficiência. Conexões
persistentes são boas se a sobrecarga (overhead) para criar uma conexão ao seu
servidor SQL for alta. Se essa sobrecarga é alta ou não depende de
vários fatores. Como, qual tipo de banco de dados é, se está ou não
na mesma máquina onde o servidor web está, o quão carregada
a máquina onde está o servidor SQL está 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.
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. Procure na documentação do seu banco de dados
por informações sobre como lidar com conexões ociosas ou abandonadas.
Aviso
Existem mais alguns cuidados a se tomar quando usando
conexões persistentes. Um deles é que, quando usando travamento de
tabela em uma conexão persistente, se o script por qualquer
razão não puder destravar a mesma, então scripts subsequentes usando a
mesma conexão serão bloqueados indefinidamente e podem exigir que você ou
reinicie o servidor httpd ou o servidor de banco de dados. Outro cuidado, é que
quando usando transações, um bloco de transação também será carregado
para o próximo script que usa aquela conexão se a execução do script
terminar antes que o bloco de transação termine. Em ambos os casos, você pode
usar register_shutdown_function() para registrar uma
função simples de limpeza para destravar suas tabelas ou reverter
suas transações. Melhor ainda, evite o problema completamente não utilizando
conexões persistentes em scripts que usam travamento de tabelas ou
transações (você ainda pode usar eles em outros casos).
Um resumo importante. Conexões persistente foram feitas para ter
um mapeamento de um-para-um com conexões normais. Isso significa que você
deve sempre ser capaz de substituir conexões
persistentes com conexões não-persistentes e isso não mudará
a maneira como seu script se comporta. Isso pode (e
provavelmente irá) mudar a eficiência do seu script, mas não o seu
comportamento!
Veja também ibase_pconnect(), ociplogon(),
odbc_pconnect(), oci_pconnect(),
pfsockopen() e pg_pconnect().