Question

We have an application that is comprised of a couple of off the shelf PHP applications (ExpressionEngine and XCart) as well as our own custom code.

I did not do the actual analysis so I don't know precisely how it was determined, but am not surprised to hear that too many MySQL connections are being left unclosed (I am not surprised because I have been seeing significant memory leakage on our dev server, where over the course of a day or two, starting from 100MB upon initial boot, the entire gig of ram gets consumed, and very little of it is cached).

So, how do we go about determining precisely which PHP code is the culprit? I've got prior experience with XDebug, and have suggested that, when we've gotten our separate, staging environment reasonably stable, that we retrofit XDebug on dev and use that to do some analysis. Is this reasonable, and/or does anybody else have more specific and/or additional suggestions?

Was it helpful?

Solution

You can use the

 SHOW PROCESSLIST  

SQL command to see what processes are running. That will tell you the username, host, database, etc that are in use by each process. That should give you some idea what's going on, especially if you have a number of databases being accessed.

More here: http://codeinthehole.com/archives/2-Monitoring-MySQL-processes.html

OTHER TIPS

This should not be caused by a php code because mysql connections are supposed to be automatically closed.

cf : http://www.php.net/manual/function.mysql-connect.php :

The link to the server will be closed as soon as the execution of the script ends, unless it's closed earlier by explicitly calling mysql_close().

Some suggestions :

  • does your developper has technically a direct access to your production mysql server ? if yes, then they probably just leave their Mysql Manager open :)
  • do you have some daily batch process ? if yes, maybe that there are some zombi process in memory

PHP automatically closes any mysql connections when the page ends. the only reason that a PHP web application would have too many unclosed mysql connections is either 1) you're using connection pooling, or 2) there's a bug in the mysql server or the connector.

but if you really want to look at your code to find where it's connecting, see http://xdebug.org/docs/profiler

As others said, PHP terminates MySQL connections created through mysql_connect or the msqli/PDO equivalents.

However, you can create persistent connections with mysql_pconnect. It will look for existing connections open and use those; if it can't find one, it will open a new one. If you had a lot of requests at once, it could have caused loads of connections to open and stay open.

You could lower the maximum number of connections, or lower the timeout for persistent connections. See the comments at the bottom of the man page for more details.

I used to run a script that polled SHOW STATUS for thread count and I noticed that using mysql_pconnect always encouraged high numbers of threads. I found that very disconcerting because then I couldn't tell when my connection rate was actually dropping. So I made sure to centralize all the places where mysql_connect() was called and eliminate mysql_pconnect().

The next thing I did was look at the connection timeouts and adjust them to more like 30 seconds because. So I adjusted my my.cnf with

connect-timeout=30

so I could actually see the number of connections drop off. To determine the number of connections you need open is dependent on how many apache workers you're running times the number of database connections they each will open.

The other thing I started doing was adding a note to my queries in order to spot them in SHOW PROCESSLIST or mytop, I would add a note column to my results like:

$q = "SELECT '".__FILE__.'.'.__LINE__."' as _info, * FROM table ...";

This would show me the file issuing the query when I looked at mytop, and it didn't foil the MySQL query cache like using

/* __FILE__.'.'.__LINE__ */ 

at the start of my query would.

I suppose another couple of things I can do, with regard to the general memory issue, as opposed specifically to MySQL, and particularly within the context of our own custom code, would be to wrap our code with calls to one or the other of the following PHP built-in functions:

memory_get_usage

memory_get_peak_usage

In particular since I am currently working on logging from some custom code, I can log the memory usage while I'm at it

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top