Currently, I'm opening a database connection in my app's initialization. It's a fairly small app, PHP if that's relevant.
Should I be connecting to the database, making calls, then closing and repeating this process for each database function I write?
For example, I have the following function which grabs the $db variable from my app's initialization.
function get_all_sections()
{
global $db;
$sql = 'select * from sections';
if (!$db->executeSQL($sql, $result))
{
throw new Exception($db->getDatabaseError());
exit();
}
$sections = array();
for ($i = 0; $i < $db->numberOfRows($result); $i++)
{
$sections[] = new Section($db->fetchArray($result, MYSQLI_ASSOC));
}
return $sections;
}
Would it be better if I opened the connection then closed it after I fetched the rows? That seems like a lot of connections that are opened and closed.
If you have connection pooling on (http://en.wikipedia.org/wiki/Connection_pool) its ok to be grabbing a new connection when you need it. HOWEVER, I'd say to be in the habit of treating any resource as "limited" and if you open the db handle keep it around for as long as possible.
Connecting to the database takes a finite amount of time. It's negligible when connecting over a domain socket or named pipe, but it can be much larger if over a network connection, or worse yet, the open Internet. Leave it connected for the life of the request at least.
Use mysql_pconnect for connection pooling, and close at the end of each operation. The thread won't really close, and the thread will be re-used. This way its both safe and efficient.
Since PHP MySQL connections are fairly light-weight, you are probably OK opening and closing the connection when needed. The same is not true of other database connections, such as connecting to SQL Server, which has rather heavy connections.
In all cases, however, do whatever makes the most sense in terms of maintainability/logic/dependencies. Then, if you find you are feeling a measurable slowdown, you can optimize those areas that need the speed-boost.
When in doubt, follow the golden rule: Don't optimize prematurely.
The simplest solution would be to use mysql_pconnect() - see here
This way if the connection is already open it will use it instead of creating a new one. If it's not it will connect again
Related
I have a normal website. It uses PHP to call a MySQL table. To save on typing it out all the time, I include() a connect.php file which connects to the database for me on every page. The website keeps getting a "mysql too many connections" error. Is it a bad idea to connect at the start of a page like this?
Should I create a new connection each time a PHP script needs it, then close that connection with mysql_close after that script is done? I had avoided doing as it would add repeated lines of code to the website but I'm wondering if that's what's causing the issue?
So at the moment my code is similar to this:
<?php
include("connect.php"); //connects to database using mysql_connect() function
...
PHP script that calls mysql
...
another PHP script that calls mysql
?>
Should I change it to something like this?
<?php
mysql_connect('host', 'username', 'password');
mysql_select_db('db');
PHP code that calls mysql
mysql_close();
...
mysql_connect('host', 'username', 'password');
mysql_select_db('db');
more PHP code that calls mysql
mysql_close();
?>
You should avoid making new connections to your database, as long as possible.
Making connection to database is a slow and expensive process. Having an opened connection consume few resources.
By the way, stop using mysql_* functions. Use mysqli_* or PDO.
Should I create a new connection each time a PHP script needs it [...] ?
Yes, that makes most sense, especially if not every page needs a mysql connection.
In PHP this works by setting up the database credentials in the php.ini file and you can just call mysql_select_db and it will automatically connect to the configured database if no connection exists so far.
If you write new code, encapsulate the database connection in an object of it's own so that you can more fine-grained control when to connect to the database.
Modern frameworks like for example Silex allow you to lazy load such central components (Services), so you have configured them and can make use of them when you need them but you don't need to worry about the resources (like the connection limit in your example).
[...] close that connection with mysql_close after that script is done?
You don't need that normally because PHP does this for you.
I do not think there is anything really wrong with this style of coding. It all depends on what kind of app you are writing. Just make sure you check your scripts well and get ride of any errors, you should be fine.
This is what i usually do
<?php session_start(); include "inc/config.php";
//require_once('chartz/lib/idiorm.php');
if ($_SESSION["login1"]== "Superadmin" or $_SESSION["login1"]== "User" or $_SESSION["login1"]=="Administrator")
{
$snames = $_SESSION["name1"];
$id = $_SESSION["id1"];
$stype = $_SESSION["login1"];
$stokperm = $_SESSION['stokperm'];
$navtype = $_GET['nav'];
include("inc/ps_pagination.php");
}
else
{
header ("location: ../../../index.php");
}
?>
Am not saying its the very best way out there, we are all still learnig...
I also thing you should take the advice of blue112 very seriously. Most of my apps are writing in the old fashion way, but Use mysqli_* or PDO is the way to go.
I have recently completed a data layer for a PHP application. In my data layer I have various methods for executing different sql tasks such as selects, inserts, deletes, etc. Coming from a .NET background, I practice opening connections, doing whatever with the connection, and closing them.
In a recent code review, I was questioned about this practice, and a colleague stated it was best to leave connections open for the life of the application. Their reasoning is that opening/closing connections is time consuming. My argument is that leaving them open is resource consuming. Following is a code sample from the data layer that executes a select query. I am fairly new to PHP so I don't really have a response for the critique. Can anyone provide any insight into this?
public static final function executeSelectQuery($qry){
$connection = mysql_connect(ADS_DB_HOST, ADS_DB_USERNAME, ADS_DB_PASSWORD) or die(ADS_ERROR_MSG . mysql_error());
$db = mysql_select_db(ADS_DB_NAME) or die(ADS_ERROR_MSG . mysql_error());
$result = mysql_query($qry) or die(ADS_ERROR_MSG . mysql_error());
mysql_close();
$results = array();
while($rows = mysql_fetch_assoc(($result))){
$results[] = $rows;
}
return sprintf('{"results":{"rows":%s}}', json_encode($results));
}
Classic case of the speed vs memory usage trade-off. There is no one-answer-fits-all to this question; it comes down to which of the two is the most important for the particular project you are undertaking.
Edit: After reading the new comments I see this project is aimed at mobile devices. In this case I would say that due to the limited memory of mobile devices (as opposed to the boatload available to most desktops nowadays) prioritising memory usage would be the right call since everyone expects mobile devices to be rather slow in comparison to desktops anyway.
Your colleague is right and this code is wrong.
Ask your self a question, what certain resources does consume an opened connection.
To add to the code review, your idea of error handling is wrong. Never use die to handle an error but throw an Exception instead.
Also, do not craft JSON manually.
return json_encode(array("results" => array ("rows" => $results)));
Also, consider to amend this unction to make it accept values for the parameterized query
I have a problem with reaching my connection limit too quickly... Am I right in thinking the following will help resolve this?
On older files using mysql_query
<?php
mysql_close($link);
if (isset($link2)) {
mysql_close($link2);
}
?>
On newer files using mysqli class
class DB extends MySQLi {
function __destruct() {
$this->close();
}
}
You may also be keeping connections open via persistent connections (pconnect), causing your database server to pool and stack up the connections. I've had troubles with this up until about PHP5.2?
Connection is closed automatically when script finishes it's work even if you forget to mysql_close(). Consider raising max_clients setting my.cnf
Also, if you are using only one database, you wont need, you don't need two connections - use one instead.
<?php
mysql_close($link);
if (isset($link2)) {
mysql_close($link2);
}
?>
This doesn't make any sense - if know that both variables may contain mysql connection resources then close the both!
Better yet - if your code is a mess and you can't make sense of it, then...
<?php
#mysql_close();
#mysql_close();
#mysql_close();
?>
But the only place you can sensibly put this (without analysing the code behaviour in some details - in which case you would know what resources you have open) is at the end of the script - which is where the connections get closed anyway.
Similarly, the destruct method is only called when all references to an object are deleted - this is marginally better but depending on the code structure you may get no benefit at all.
It makes far more sense to identify which URLs are taking a long time to process and trying to re-factor the code (both PHP and SQL) in these.
As all of you know when you fork the child gets a copy of everything, including file and network descriptors - man fork.
In PHP, when you use pcntl_fork all of your connections created with mysql_connect are copied and this is somewhat of a problem - php docs and SO question. Common sense in this situation says close the parent connection, create new and let the child use the old one. But what if said parent needs create many children ever few seconds? In that case you end up creating loads of new connections - one for every bunch of forks.
What does that mean in code:
while (42) {
$db = mysql_connect($host, $user, $pass);
// do some stuff with $db
// ...
foreach ($jobs as $job) {
if (($pid = pcntl_fork()) == -1) {
continue;
} else if ($pid) {
continue;
}
fork_for_job($job);
}
mysql_close($db);
wait_children();
sleep(5);
}
function fork_for_job($job) {
// do something.
// does not use the global $db
// ...
exit(0);
}
Well, I do not want to do that - thats way too many connections to the database. Ideally I would want to be able to achieve behaviour similar to this one:
$db = mysql_connect($host, $user, $pass);
while (42) {
// do some stuff with $db
// ...
foreach ($jobs as $job) {
if (($pid = pcntl_fork()) == -1) {
continue;
} else if ($pid) {
continue;
}
fork_for_job($job);
}
wait_children();
sleep(5);
}
function fork_for_job($job) {
// do something
// does not use the global $db
// ...
exit(0);
}
Do you think it is possible?
Some other things:
This is php-cli script
I've tried using mysql_pconnect in the first example but as far as I can tell there is no difference - the mysql server receives as much new connections. Maybe that's because it is cli and pconnect does not work as it was in mod_php. As Marc has noticed - pconnect in php-cli does not make sense.
The only thing you could try, is to let your children wait until each other child has finished its job. This way you could use the same database connection (provided there aren't any synchronization issues). But of course you'll have a lot of processes, which is not very good too (in my experience PHP has quite a big memory usage). If having multiple processes accessing the same database connection is not a problem, you could try to make "groups" of processes which share a connection. So you don't have to wait until each job finished (you can clean up when the whole group finished) and you don't have a lot of connections either..
You should ask yourself whether you really need a database connection for your worker processes. Why not let the parent fetch the data and write your results to a file?
If you do need the connection, you should consider using another language for the job. PHPs cli itself is not a "typical" use case (it was added in 4.3) and multiprocessing is more of a hack than a supported feature.
If the child calls exec() or _exit() fairly quickly, you're alright. The problem is if the child sticks around and holds on to copies of your file descriptors.
You could also use posix_spawn if PHP has an API for that. That might work well.
My advice (from personal experience on the same issue) is to close the connection before pcntl_fork() then open new connections in parent and/or the child process as needed.
If you open a new connection in the parent process then you have to block the SIGCHLD signal (using pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD)). No special care is needed in the children processes (except when they also launch their own children, becoming parents this way.)
SIGCHLD is a signal that is received by the parent process when one of its children completes.
During the communication with the server, the MySQL client library uses nanosleep() to suspend the execution of the program for some amounts of time. The sleep() functions return when the time passes but they also return before the time passes if the process receives a signal while it is suspended.
When nanosleep() returns because of a signal (i.e. before enough time has passed), the MySQL library gets confused and reports the error "MySQL server has gone away" and the connection cannot be used any more. It is a false alarm, the MySQL server is still there waiting for queries but the client code is fooled by the signal arrived at the wrong moment.
If you are interested in receiving the SIGCHLD signal then you can block it before running a MySQL query then unblock it again (to avoid it being received during the communication with MySQL server.
Also read this answer and this answer I wrote on similar questions (it's the same information, but with more details and explanation.)
Do I need to explicitly kill and/or close a mysqli connection at the end of a script. At the moment, I do neither, and it works, but I don't have much load.
I've heard that there is connection pooling, and mysqli connections are re-used... do I need to close the connection then at all?
You should always close your connections at the end of the main script. If you uses some php5 and object to handle your DB just think about using __destruct() to automatically close it
http://php.net/manual/en/language.oop5.decon.php
No it is not necessary to close a mysql connection at the end of a script. PHP does it automatically.
it is not necessary but generally that's good practice. I personally, when wish to boost error-checking mechanism, you $con->close() for almost each function. e.g:
if($stmt = $db->prepare($statment))
{
if($db->bind_param($str, $param1, $param2))
{
// the rest of the code and error checking
}
else
}
$db->close();
}
}
else
{
$db->close();
}
This makes OOP necessary. Since you can simply write function doing this automatically with many other security checks added. codeIgniter as a framework has nice DB connectors whith superb security at a basic general level.