Connect vs pconnect
Uit Yapf
Inhoud |
Inleiding
Veel mensen denken dat het gebruik van pconnect het totaal aantal gebruikte connecties drastisch vermindert. Niets is minder waar. Je scripts hebben nog steeds even vaak de database nodig en dus heb je nog altijd evenveel connecties nodig en dus krijg je niet minder connecties.
Pconnect houdt database verbindingen open, ook als het script gestopt is en zelfs als je in je script de 'close()' functie gebruikt. Het voordeel hiervan is dat de verbinding niet telkens opnieuw moet worden opgebouwd en dat scheelt weer een paar milliseconden.
Wat is het probleem?
PHP gebruikt 'connection pooling' voor de database connecties. Dit betekent dat elke geopende verbinding naar een server X met username Y en database Z terechtkomt in een pool van open verbindingen totdat de verbinding weer wordt gesloten. Elke keer dat een script een verbinding naar een database opent kijkt PHP eerst in de pool of dat script toevallig al exact zo'n verbinding open heeft. Als dat zo is dan geeft PHP opnieuw de 'link identifier' van die verbinding. Als de database/user/host hetzelfde zijn als bij een reeds geopende verbinding dan wordt dus geen nieuwe verbinding gemaakt.
Dit werkt dus niet zoals je verwacht:
<?php$conn_one = pg_connect(foo,bar);
$conn_two = pg_connect(foo,bar);
?>
Zodra PHP de tweede pg_connnect() uitvoert zoekt hij in de pool en komt daar de verbinding van $conn_one tegen die ook gaat naar 'foo,bar' en dus geeft PHP dezelfde verbinding terug. Nu zijn $conn_one en $conn_two dus identiek, je kunt een query draaien op $conn_one en de resultaten daarvan opvragen via $conn_two.
Als het script sluit dan wordt de verbinding weer uit de pool weggehaald.
Dit gedrag kun je handmatig veranderen door PGSQL_CONNECT_FORCE_NEW als derde parameter mee te geven aan pg_connect. Deze parameter zorgt er voor dat PHP de pool overslaat en hoedanook en nieuwe verbinding gaat maken.
Wat doet pconnect dan?
Pconnect maakt verbindingen die na het einde van het script niet meer uit de pool worden weggehaald. De verbindingen blijven open en beschikbaar, ook al roep je zelf functies als pg_close() aan.
Maar een verbinding kan maar door één script tegelijk worden gebruikt dus als je twee scripts tegelijk draait dan worden er nog steeds twee verbindingen geopend en die blijven dus open.
Sterker nog, om meerdere bezoekers tegelijk te kunnen afhandelen start de webserver meerdere copieen van zichzelf (meerdere processen) en die houden allemaal hun eigen connection-pool bij. Tijdens het browsen kunnen er op een server makkelijk tientallen zoniet honderden van die processen lopen en ze handelen elk semi-willekeurig page-requests af en na verloop van tijd hebben alle lopende webserver processen zo'n beetje alle scripts wel eens gedraaid en hebben ze dus ook allemaal wel eens elk van de verbindingen geopent.
Even rekenen: stel je hebt maximaal 100 webserver processen die in de piekuren allemaal actief zijn. Dat betekent dat er 100 van die scripts gedraaid worden en dat er dus ook 100 verbindingen open staan.
Stapje verder, je stel je maakt een nieuwe site aan en daarvoor gebruik je een nieuwe database. Uiteraard kunnen alle webserver processen dat nieuwe script ook draaien en nu houden ze elk dus elk twee verbindingen open, 200 in totaal.
En als je dus op een shared-server zit, met 35 klanten (dus 35 databases) en max 500 webserver processen dan heb je dus 35x500=17500 verbindingen nodig.
En elke verbinding neemt ongeveer 2MB geheugen in beslag, dus je hebt 35GB werkgeheugen nodig.
Zie je het probleem?
Samengevat
Pconnect is goed als elke milliseconde nodig hebt om de benodigde performance te halen en dan alleen als jij controle hebt over de server.
Als je geen controle hebt over de server, gebruik dan ook geen pconnect!