Обсуждение: PHP Connections

Поиск
Список
Период
Сортировка

PHP Connections

От
"David Busby"
Дата:
List,
    Which way to connect is better for my scripts?

a global
  $db = pg_connect('asdfasdfasdfasdf');
and every function can have
  global $db;
at the top?

or like this?

function db_handle()
{
  return pg_connect('asdfasdfasdfasdfadsf');
}

and everyplace needed use `db_handle()` so I call pg_exec like

$rs = pg_exec(db_handle(),"select everything from everywhere"));

So does that db_handle() make a new connection each time?
I'm really looking for the way to optimise my connection usage.

David Busby
Systems Engineer
busby@pnts.com


Re: PHP Connections

От
Lynna Landstreet
Дата:
on 8/5/03 1:44 PM, David Busby at busby@pnts.com wrote:

> Which way to connect is better for my scripts?
>
> a global
> $db = pg_connect('asdfasdfasdfasdf');
> and every function can have
> global $db;
> at the top?
>
> or like this?
>
> function db_handle()
> {
> return pg_connect('asdfasdfasdfasdfadsf');
> }
>
> and everyplace needed use `db_handle()` so I call pg_exec like
>
> $rs = pg_exec(db_handle(),"select everything from everywhere"));
>
> So does that db_handle() make a new connection each time?
> I'm really looking for the way to optimise my connection usage.

I'm more often found asking questions than answering them here, but I think
I'll have a go at this one. To my knowledge, a new connection is a bigger
hit on the server than a query, so from an efficiency standpoint it's best
to have fewer connections, and just make your queries from an existing
connections where possible. So you definitely don't want to be connecting
anew every time you call a function. Some web hosts who allot you a certain
amount of database traffic per plan and charge extra if you have more weight
connections more heavily than queries.

So the first option you have above is the best - the second would indeed
connect every time you called that function.

On my site I have one global include file with the db connection in it, and
just call it in the head section of each page. The code just references the
$db handle where it needs it, rather than connecting again. Even with that,
I keep wondering if it might be better to use a persistent connection that
would last from page to page rather than each page connecting over again.
But the problem there is that I don't necessarily know which page visitors
are going to come in on, so I need to make sure they always get a
connection, and connecting once per page seems like a reasonable compromise.

But hey, come to think of it, maybe I could turn the pg_connect into a
pg_pconnect and just have it check to see if $db already exists before
connecting - that way there'd be only one connection per site visit! Cool,
your question gave me a new idea... :-)


Lynna
--
Resource Centre Database Coordinator
Gallery 44
www.gallery44.org


Re: PHP Connections

От
"scott.marlowe"
Дата:
On Tue, 5 Aug 2003, David Busby wrote:

> List,
>     Which way to connect is better for my scripts?
>
> a global
>   $db = pg_connect('asdfasdfasdfasdf');
> and every function can have
>   global $db;
> at the top?
>
> or like this?
>
> function db_handle()
> {
>   return pg_connect('asdfasdfasdfasdfadsf');
> }
>
> and everyplace needed use `db_handle()` so I call pg_exec like
>
> $rs = pg_exec(db_handle(),"select everything from everywhere"));
>
> So does that db_handle() make a new connection each time?
> I'm really looking for the way to optimise my connection usage.

All you're really doing here is wrapping your connects in a function.
since you (should) only connect at the top of the script, this function
will only be called once, and the difference in performance is negligable.
But the gains are worth the trouble because you can then switch out common
parts of each function you'd always do rather than cut and paste it into
all your scripts.

Taking this a step fruther, put all your pg_xxx functions
you'll use into an abstract layer that has them named like:

<?php
function db_connect($database){
    $conn_str = "host=w.x.y.z user=fred dbname=$dbname";
    return pg_connect($conn_str);
}

function db_query($query){
    more code here.
}
?>

Toss in some error checking and you can use those functions for things
like controlling which server or username the scripts are connecting from.
Then put them in the php_include path somewhere and just include_once()
the function lib.

This allows you to "switch out" things like databases or database servers
or accounts or what not in one fell swoop with ease.


Re: PHP Connections

От
"scott.marlowe"
Дата:
On Tue, 5 Aug 2003, Lynna Landstreet wrote:

> On my site I have one global include file with the db connection in it, and
> just call it in the head section of each page. The code just references the
> $db handle where it needs it, rather than connecting again. Even with that,
> I keep wondering if it might be better to use a persistent connection that
> would last from page to page rather than each page connecting over again.
> But the problem there is that I don't necessarily know which page visitors
> are going to come in on, so I need to make sure they always get a
> connection, and connecting once per page seems like a reasonable compromise.
>
> But hey, come to think of it, maybe I could turn the pg_connect into a
> pg_pconnect and just have it check to see if $db already exists before
> connecting - that way there'd be only one connection per site visit! Cool,
> your question gave me a new idea... :-)

Be VERY wary of persistant connections.  They are fraught with danger and
can cause your server to present the "too many connections" error message
after being up for a while.

The reason is the dirt simple persistant connection technology in
PHP/Apache.  Each persistant connection stays open until the child process
dies or the connection errors or times out.  Since Postgresql, by default,
doesn't time out idle connections, and apache, by default doesn't kill
it's children every so often, only if there's too many, and postgresql, by
experience never seems to crash (backend or especially postmaster for me)
this means that each persistant connection functioanlly lasts forever.

So, if apache is configured for 150 children (the default) and postgresql
is configured for 32 children (again, the default) then after the server's
been up and under load, it is quite possible for all the connections to
postgresql to get exhausted and for the 33rd connection to get a too many
connection errors.

Easy fix, just crank up max backends, right?  Well, sorta.  The rule of
TANSTAAFL (there ain't no such thing as a free lunch.)  If Postgresql has
150+ connections sitting open and idle, it's likely not gonna run as fast
as if it had only 3 or 4 children open.

So, it's generally better to turn down the number of apache children to
control this problem.

But that brings up apache's keep alive mechanism, a standard part of the
http/1.1 protocol, which basically means that whichever request came from
ip w.x.y.z last time will likely get serviced by the same child, which
will stay assigned to that client as long as he clicks every X seconds
(usually 15 or so).

If apache has 30 keep alive connects going, and a max children setting of
150, when a new request from a new client comes along, it will NOT reuse
one of the pre-existing children unless its keep alive has timed out.  So,
if you've got 100 distinct users clicking every 7 to 15 seconds, you may
find apache spawning LOTS of children if you haven't turned it down.

Now, if the max children are set to 30, and apache has 30 keep alive
connections going, it will reuse one of the pre-existing child processes.

That means that whatever page cache was being kept for that client likely
is lost (but still probably in kernel buffers, so no huge loss.)

Now, things get real ugly when you start connecting to different
databases.

Say I have 64 databases, and my scripts have equal chances of using any
one of them depending on which customer site whatever they are hitting.

Now we look at pgsql.max_persistent.  this setting is PER CHILD.  Not for
the whole apache/php server.  If you have this set to unlimited, and your
child processes are hopping all over due to keep alive timeout/out of
children mentioned above, then you could theoretically have 64 persistant
connections open, per child.  That's 1920 connections.   ugh.

It's important to understand that php persistant connects are NOT
connection pooling in the classic java sense, and if not configured
properly, can bring an apache/php/postgresql server to it's knees under
fairly light load.

Put another way, whereas non-persistant connections have a slow degrade
under increasing of load, persistant connections, if improperly
configured, fail catastrophically under increasing load.

Configured properly:

pgsql.max_persistent set to 1 to 4
apache max_children set to 30 to 100
max_connections set to the two numbers above multiplied by each other,
plus an extra dozen or so for fudge factor

they can work quite well and help a busy web site.  But they aren't always
a gain, since having too many connections open at once can cause a
performance issue too.


Re: PHP Connections

От
Lynna Landstreet
Дата:
on 8/5/03 3:07 PM, scott.marlowe at scott.marlowe@ihs.com wrote:

> On Tue, 5 Aug 2003, Lynna Landstreet wrote:
>
>> But hey, come to think of it, maybe I could turn the pg_connect into a
>> pg_pconnect and just have it check to see if $db already exists before
>> connecting - that way there'd be only one connection per site visit! Cool,
>> your question gave me a new idea... :-)
>
> Be VERY wary of persistant connections.  They are fraught with danger and
> can cause your server to present the "too many connections" error message
> after being up for a while. <rest snipped>

Hmmm, OK. I didn't realize they didn't time out. Maybe it's best to leave it
the way it is now, with just one pg_connect being called in the head of each
document. Thanks.


Lynna
--
Resource Centre Database Coordinator
Gallery 44
www.gallery44.org


Re: PHP Connections

От
"scott.marlowe"
Дата:
On Tue, 5 Aug 2003, Lynna Landstreet wrote:

> on 8/5/03 3:07 PM, scott.marlowe at scott.marlowe@ihs.com wrote:
>
> > On Tue, 5 Aug 2003, Lynna Landstreet wrote:
> >
> >> But hey, come to think of it, maybe I could turn the pg_connect into a
> >> pg_pconnect and just have it check to see if $db already exists before
> >> connecting - that way there'd be only one connection per site visit! Cool,
> >> your question gave me a new idea... :-)
> >
> > Be VERY wary of persistant connections.  They are fraught with danger and
> > can cause your server to present the "too many connections" error message
> > after being up for a while. <rest snipped>
>
> Hmmm, OK. I didn't realize they didn't time out. Maybe it's best to leave it
> the way it is now, with just one pg_connect being called in the head of each
> document. Thanks.

they can be set to, but it's by request, not over time.  max requests per
child or some such setting.  Setting it low enough helps prevent certain
problems.  It's just that the default settings for apache/php/postgresql
are all designed to make your box go kaboom if you use persistant
connects.  :-)


Re: PHP Connections

От
Gerd Terlutter
Дата:
David Busby wrote:
> List,
>     Which way to connect is better for my scripts?
>
> a global
>   $db = pg_connect('asdfasdfasdfasdf');
> and every function can have
>   global $db;
> at the top?
>
> or like this?
>
> function db_handle()
> {
>   return pg_connect('asdfasdfasdfasdfadsf');
> }
>
> and everyplace needed use `db_handle()` so I call pg_exec like
>
> $rs = pg_exec(db_handle(),"select everything from everywhere"));
>
> So does that db_handle() make a new connection each time?
> I'm really looking for the way to optimise my connection usage.
>

the glob is better when you use it undefined times in each of your
script. another way is
$dbh = db_handle();
$dbh->doThis(param);
$dbh->doThat(param);

or perhaps write an own class with specials for your page. e.g.
functions like update, getFrom, insertInto, deleteFrom.
best regards,
Gerd

--
--------------------------------------------------------
# Gerd Terlutter        | Mueller+Blanck Software GmbH #
# gerd@MplusB.de        | Gutenbergring 38             #
# gerd.terlutter@web.de | D-22848 Noderstedt           #
# tel:0171/6992579      | tel:+49 40 500 171-1         #
# Buero:040/500171-17   | fax:+49 40 500 171-71        #
--------------------------------------------------------