Conexiones persistentes a bases de datos
Las conexiones persistentes son enlaces que no se cierran al
finalizar la ejecución de un script. Cuando se solicita una
conexión persistente, PHP comprueba si ya hay una idéntica
(que ya estuviera abierta antes), utilizándola si
existe. Si no, crea el enlace. Una conexión «idéntica»
es una conexión que fue abierta por el mismo host, con
el mismo usuario y la misma contraseña (donde sea aplicable).
Aquellos que no están plenamente familiarizados con la forma en que trabajan y
distribuyen la carga los servidores web podrían confundir para qué
sirven las conexiones persistentes. En particular, con ellas no
se pueden abrir «sesiones de usuario» en un mismo enlace,
no se puede construir una transacción
eficiente y no hacen muchísimas otras cosas.
De hecho, para ser sumamente precisos, las conexiones
persistentes no proporcionan ninguna
otra funcionalidad que no fuera posible realizar con sus hermanas
no persistentes.
¿Por qué?
Esto tiene que ver con la manera en que los servidores web funcionan. Existen
tres formas en las cuales un servidor web puede generar páginas web usando PHP.
El primer método es emplear PHP como una «envoltura» CGI. Cuando se ejecuta
de esta forma, se crea y se destruye una instancia del intérprete de PHP
por cada solicitud de página (para una página de PHP) al servidor web.
Debido a que esta instancia se destruye después de cada solicitud, cualquier recurso que
adquiera (tal como un enlace a un servidor de base de datos SQL) es cerrado
en la destrucción de dicha instancia. En este caso, no se gana nada
utilizando conexiones persistentes: simplemente no persisten.
El segundo método, y más popular, es ejecutar PHP como módulo en un
servidor web multiproceso, lo que actualmente solo incluye a Apache.
Un servidor multiproceso normalmente tiene un proceso (el padre) que
coordina un grupo de procesos (sus hijos) los cuales son los que realmente
hacen el trabajo de servir páginas web. Cuando una solicitud proviene de
un cliente, esta es cedida a uno de los hijos que no esté ya
sirviendo a otro cliente. Esto significa que cuando el mismo cliente
hace una segunda solicitud al servidor, esta podría ser servida por un
proceso hijo diferente a la primera vez. Cuando se abre una conexión
persistente, cada página que solicite servicios SQL puede reusar
la misma conexión establecida al servidor SQL.
El último método es utilizar PHP como complemento para un servidor web
multihilo. Actualmente, PHP tiene soporte para ISAPI, WSAPI, y NSAPI
(en Windows), las cuales permiten usar PHP como un complemento en servidores
multihilo como Nestcape FastTrack (iPlanet), Microsoft Internet Information
Server (IIS), y O'Reilly's WebSite Pro. El comportamiento es esencialmente
el mismo para el modelo multiproceso descrito antes.
Si las conexiones persistentes no tienen ninguna funcionalidad adicional,
¿para que son útiles?
La respuesta es extremadamente simple: Eficacia. Las conexiones
persistentes son buenas si la sobrecarga para crear enlaces al servidor
SQL es alta. Que esta sobrecarga sea realmente alta o no depende
de muchos factores, como el tipo de base de datos que se emplea, si esta
se encuentra en la misma computadora en la que está el servidor web, la
carga de la máquina donde está el servidor SQL, etc. En resumidas cuentas,
si la sobrecarga de una conexión es alta, las conexiones persistentes
ayudan considerablemente, haciendo que un proceso hijo únicamente se
conecte una vez durante su vida útil, en lugar de hacerlo cada vez
que procese una página que requiera una conexión al servidor
SQL. Esto significa que cada hijo que abra una conexión
persistente tendrá su propia conexión persistente abierta al
servidor. Por ejemplo, si se tienen 20 procesos hijos diferentes que
ejecutan un script que realiza una conexión persistente al servidor SQL,
se tendrán 20 conexiones diferentes al servidor SQL, una por cada
hijo.
Observe, sin embargo, que esto puede tener algunos inconvenientes si se está usando
una base de datos con un limite de conexiones que sea excedido por las conexiones
persistentes hijas. Si la base de datos tiene un limite de 16 conexiones
simultáneas, y en el curso de una sesión de un servidor ocupado 17 hilos
hijos intentan conectarse, uno de ellos no será capaz de hacerlo. Si un
script contiene errores que impidan el cierre de las conexiones
(como un bucle infinito), la mencionada base de datos con solamente 16 conexiones
podría saturarse rápidamente. Compruebe la documentación de su base de datos para
obtener información sobre el manejo conexiones abandonadas o inactivas.
Advertencia
Hay un par de advertencias más a tener en cuenta cuando se
utilizan conexiones persistentes. Una es que cuando se usan bloqueos
de tablas con una conexión persistente, si el script por alguna razón
no puede liberar el bloqueo, los scripts subsiguientes que empleen la
misma conexión quedarán en espera indefinidamente, puediendo ser necesario
reiniciar el servidor httpd o el servidor de la base de datos. Otra cosa es
que cuando se usan transacciones, un bloque de las mismas también acarrearía
al siguiente script que utiliza la conexión si la ejecución del script
termina antes de que el bloque lo haga. En cualquier caso, se puede
usar register_shutdown_function() para registrar una
función de limpieza para desbloquear las tablas o deshacer las
transacciones. Mejor aún, evitar este problema por completo no usando
conexiones persistentes en scripts que utilicen bloqueos de tablas o
transacciones (aún se pueden usar en otros lugares).
Un resumen importante. Las conexiones persistentes fueron diseñadas para tener
una correspondencia uno a uno con las conexiones normales. Esto significa que
siempre se pueden reemplazar las conexiones
persistentes por conexiones no persistentes, no cambiando así
la forma de funcionar un script. Esto podría (y
probablemente lo hará) cambiar la eficacia del script, aunque no su
funcionamiento.
Véanse también ibase_pconnect(), ociplogon(),
odbc_pconnect(), oci_pconnect(),
pfsockopen() y pg_pconnect().