MySql and ADODB5 - Max connections - php

Here's an example of php code to make a connection to mysql and perform a select query using adodb :
include('adodb.inc.php'); # load code common to ADOdb
$db = &ADONewConnection('mysql');
$db->PConnect("localhost", "root", "password", "database");
$recordSet = &$conn->Execute('select * from products');
if (!$recordSet)
print $conn->ErrorMsg();
else
while (!$recordSet->EOF) {
print $recordSet->fields[0].' '.$recordSet->fields[1].'<BR>';
$recordSet->MoveNext();
}
$recordSet->Close(); # optional
$conn->Close(); # optional
?>
Do i have to use
$db = &ADONewConnection('mysql');
$db->PConnect("localhost", "root", "password", "database");
and
$recordSet->Close(); # optional
$conn->Close(); # optional
each time i want to make a query to unsure the error of max_connection reached ?
How can i manage when 1000 users or more are connected to my website with MySQL's max_connection = 100 ?

When the maximum number of connections has been reached, your $db->PConnect should throw an exception or return an error code (I don't know this driver too much, please check the man pages). You must watch this error and act accordingly in case of error. Typically, wait a few seconds, and try again a couple of times before returning an error to the user.
Now, the max_connection is the limit of concurrent connections. 1000 users connected to your application are (hopefully) not all running a query at the same time, so you should be safe for a while. At the end of a script execution, all connections are closed (or returned to the pool in your case), and become available to other users. So you will not reach your limit of 100 unless 100 users are actually clicking at the same time on some link in your application.
But you should write your scripts so that they open (or acquire) a connection as late as possible during the course of their execution, and close (or release) the connection as early as possible. This way, the connection is held for a span of time as short as possible, making it less likely to hit the limit.
Now, if you do reach the limit, then there is nothing else you can do but increasing the limit. The only workaround is to put exceeding connection requests on hold (as I suggest in the first paragraph).

Related

How do I force reconnecting to my database in php?

I wanted my web system to automatically reconnect to the database if it reaches to maximum user connection. Or is there anyway i could reload the page automatically till it is connected to the database
$conn = new mysqli(DB_HOST,DB_USER,DB_PSWD,DB_NAME);
if($conn->connect_error)
die("Failed to connect database ".$conn->connect_error );
You can setting the retry variable($retry) as a flag to mark the DB connection status with default value you want. While connect DB , if it's ok then update retry flag = 0($retry=0) , else reduce the retry one unit ($retry--). Also you don't die process when have error exception.
You can enclose the connection in a function and call it many times you want to retry the connection:
function connectDB(DB_HOST,DB_USER,DB_PSWD,DB_NAME)
{
return $conn = new mysqli(DB_HOST,DB_USER,DB_PSWD,DB_NAME);
}
if(connectDB()->connect_error)
{
sleep(1);
if(connectDB()->connect_error)
{
die("Failed to connect database ".$conn->connect_error );
}
}
With sleep(1) you delay the script to retry the connection after 1 second.
Anyway, you should find the cause of the connection error and solve it; this solution may help you in the case the server is sometimes slow to respond.

"Could not connect. Too many connections" Error in MySQLi

I have the following code
function openDBConn($params){
$conn_mode = $params['conn_mode'];
$db_conn = $params['db_conn'];
//create connections
if(empty($db_conn->info)) {
$db_conn = new mysqli("localhost", $user, $password, "database");
$db_conn->set_charset('UTF8');
$mysqli_error = $db_conn->connect_error;
}
if($mysqli_error !== NULL){
die('Could not connect <br/>'. $mysqli_error);
}else{
return $db_conn;
}
}
//close db connection
function closeDBConn( $params ){
$db_conn = $params['db_conn'];
$db_conn->close;
}
//used as below
$db_conn = openDBConn();
save_new_post( $post_txt, $db_conn );
closeDBConn( array('db_conn'=>$db_conn));
From time to time, I get the "Could not connect. Too many connections" error.
This tends to happen when I have Google bot scanning my website.
This problem seems to have started ever since upgrading to MySQLi from MySQL.
Is there any advice on how ensure all connections are closed?
Thanks
You need to increase the number of connections to your MySQL server (the default is only 100 and typically each page load consumes one connection)
Edit /etc/my.cnf
max_connections = 250
Then restart MySQL
service mysqld restart
http://major.io/2007/01/24/increase-mysql-connection-limit/
Some hosters have a hard limit how many open database connections your are allowed to have. Maybe you want to contact your hoster to know how many you are allowed to open. For websites with hight traffic load more connections can be helpful.
Do you have access to the server directly or is it a hosted solution?
If you have direct access you can check the mySQL config files to see how many connections are allowed and increase it.
If you don't you might want to contact your webhost about increasing the limit and see if they will comply.

Why do we have to close the MySQL database after a query command?

I'm starter.
I want to know what will happen if we don't close the MySQL connection.
1- Is it possible to open more than one database if we don't close them? I mean can we open more than one database in a same time?
2- Does closing database increase the speed?
3- Is it necessary to close the database or it is optional?
Look at this code. I don't use "mysql_close()" so I don't close the database after each request. There are a lot of requests for this PHP page. Maybe 50000 per each minute. I want to know closing database is necessary for this code or no?
<?php
//Include the file that lets us to connect to the database.
include("database/connection.php");
//Call "connect" function to connect to the database.
connect("database", "localhost", "root", "", "user");
//The GPRS module send a string to this site by GET method. The GPRS user a variable named variable to send the string with.
$received_string = $_GET["variable"];
//Seprates data in an array.
$array_GPRS_data = explode(",", $received_string);
//we need to remove the first letter.
$array_GPRS_data[9] = substr($array_GPRS_data[9], 1);
$array_GPRS_data[13] = substr($array_GPRS_data[13], 4, 2).substr($array_GPRS_data[13], 2, 2).substr($array_GPRS_data[13], 0, 2);
//Query statement.
$query = "INSERT INTO $array_GPRS_data[17](signal_quality, balance, satellite_derived_time, satellite_fix_status, latitude_decimal_degrees,
latitude_hemisphere, longitude_decimal_degrees, longitude_hemisphere, speed, bearing, UTCdate, theChecksum)
VALUES('$array_GPRS_data[0]', '$array_GPRS_data[1]', '$array_GPRS_data[5]', '$array_GPRS_data[6]', '$array_GPRS_data[7]',
'$array_GPRS_data[8]', '$array_GPRS_data[9]', '$array_GPRS_data[10]', '$array_GPRS_data[11]', '$array_GPRS_data[12]', '$array_GPRS_data[13]',
'$array_GPRS_data[16]')";
//Run query.
$result = mysqli_query($query);
//Check if data are inserted in the database correctly.
if($result)
{
echo("*#01");
}
else
{
echo("Error: 001");
echo (mysqli_error());
}
?>
Yes, you can have multiple database connections. You are not opening a database, you are opening a database connection. The database is 'open' (i.e. running) all of the time, generally speaking, whether you are connected to it or not.
Depends... if you only have one open connection on a page, then you don't need to close it because it will automatically close when PHP is done. If you have many, then you could potentially make the database server slower, or make the database server run out of available connections (it can only have a certain number of connections open at the same time). That said, most modern database servers can handle hundreds of concurrent connections.
Optional, but recommended. It's not a big deal for small-medium projects (i.e. if you have less than 100 concurrent visitors at any given time, you probably won't have any issues regardless). Since you have many thousand visitors per minute, you should actively close the database connection as soon as you are done with it, to free it up as soon as possible.
Once you connect to the database it is not necessary to close. As non-persistent connection automatically closed at the end of script execution.
Follow this for more information

How can I get php pdo code to keep retrying to connect if there are too many open connections?

I have an issue, it has only cropped up now. I am on a shared web hosting plan that has a maximum of 10 concurrent database connections. The web app has dozens of queries, some pdo, some mysql_*.
Loading one page in particular peaks at 5-6 concurrent connections meaning it takes a minimum of 2 users loading it at the same time to spit an error on one or both of them.
I know this is inefficient, I'm sure I can cut that down quite a bit, but that's what my idea is at the moment is to move the pdo code into a function and just pass in a query string and an array of variables, then have it return an array (partly to tidy my code).
THE ACTUAL QUESTION:
How can I get this function to continue to retry until it manages to execute, and hold up the script that called it (and any script that might have called that one) until it manages to execute and return it's data? I don't want things executing out of order, I am happy with code being delayed for a second or so during peak times
Since someone will ask for code, here's what I do at the moment. I have this in a file on it's own so I have a central place to change connection parameters. the if statement is merely to remove the need to continuously change the parameters when I switch from my test server to the liver server
$dbtype = "mysql";
$server_addr = $_SERVER['SERVER_ADDR'];
if ($server_addr == '192.168.1.10') {
$dbhost = "localhost";
} else {
$dbhost = "xxxxx.xxxxx.xxxxx.co.nz";
}
$dbname = "mydatabase";
$dbuser = "user";
$dbpass = "supersecretpassword";
I 'include' that file at the top of a function
include 'db_connection_params.php';
$pdo_conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
then run commands like this all on the one connection
$sql = "select * from tbl_sub_cargo_cap where sub_model_sk = ?";
$capq = $pdo_conn->prepare($sql);
$capq->execute(array($sk_to_load));
while ($caprow = $capq->fetch(PDO::FETCH_ASSOC)) {
//stuff
}
You shouldn't need 5-6 concurrent connections for a single page, each page should only really ever use 1 connection. I'd try to re-architect whatever part of your application is causing multiple connections on a single page.
However, you should be able to catch a PDOException when the connection fails (documentation on connection management), and then retry some number of times.
A quick example,
<?php
$retries = 3;
while ($retries > 0)
{
try
{
$dbh = new PDO("mysql:host=localhost;dbname=blahblah", $user, $pass);
// Do query, etc.
$retries = 0;
}
catch (PDOException $e)
{
// Should probably check $e is a connection error, could be a query error!
echo "Something went wrong, retrying...";
$retries--;
usleep(500); // Wait 0.5s between retries.
}
}
10 concurrent connections is A LOT. It can serve 10-15 online users easily.
Heavy efforts needed to exhaust them.
So there is something wrong with your code.
There are 2 main reasons for it:
slow queries take too much time and thus serving one hit uses one mysql connection for too long.
multiple connections opened from every script.
The former one have to be investigated but for the latter one it's simple:
Do not mix myqsl_ and PDO in one script: you are opening 2 connections at a time.
When using PDO, open connection only once and then use it throughout your code.
Reducing the number of connections in one script is the only way to go.
If you have multiple instances of PDO class in your code, you will need to add that timeout handling code you want to every call. So, heavy code rewriting required anyway.
Replace these new instances with global $pdo; instead. It will take the same amount of time but it will be permanent solution, not temporary patch as you want it.
Please be sensible.
PHP automatically closes all the connections st the end of the script, you don't have to care about closing them manually.
Having only one connection throughout one script is a common practice. It is used by ALL the developers around the world. You can use it without any doubts. Just use it.
If you have transaction and want to log something in database you sometimes need 2 connections in one script

Best approach to see if a MySQL Server is up and running

I have a Master - Slave setup for a web application written in PHP. I have a pool of slaves I use for reading, and a Master that is used for writes (and reads if a write has been sent this request). I would like to incorporate an automated system for removed crashed servers from the read pool. Currently I am using:
foreach($readers as $reader)
{
$fp = #fsockopen($reader['host'],3306,$errno,$errstr,1);
if(!$fp)
{
//Remove from pool
}
unset($fp);
}
My primary question is there a more reliable method. I have had quite a few false positives, and vice versa because it is not actually checking for a MySQL server, but rather just a connection on port 3306. Is there a way to check for a MySQL server without raising an exception, which is the behaviour of the PDO and MySQLi extensions in PHP.
You could just use mysql_connect() and check the result for false, and close the connection right away on success. You can make a dummy account with no privileges for that if you like.
That's really the only reliable way, especially if you want to distinguish a running MySQL server from any other random process listening on port 3306.
You could use mysql_ping() to check if a current DB Connection you have open is still alive
Here is the example posted at http://www.php.net/manual/en/function.mysql-ping.php
<?php
set_time_limit(0);
$conn = mysql_connect('localhost', 'mysqluser', 'mypass');
$db = mysql_select_db('mydb');
/* Assuming this query will take a long time */
$result = mysql_query($sql);
if (!$result) {
echo 'Query #1 failed, exiting.';
exit;
}
/* Make sure the connection is still alive, if not, try to reconnect */
if (!mysql_ping($conn)) {
echo 'Lost connection, exiting after query #1';
exit;
}
mysql_free_result($result);
/* So the connection is still alive, let's run another query */
$result2 = mysql_query($sql2);
?>
The best way to check if any service is alive is to actually use it. So for MySQL try to connect and execute some fast query, for web server try to fetch some file, for PHP try to fetch some simple script...
For MySQL master/slave setup, one of the solutions is to actually check the state of replication. You can check how many transactions is the slave behind master and decide to stop using that slave when/while it has old data. (I don't do the replication myself, but I think you need to compare the variables Read_Master_Log_Pos and Relay_Log_Pos)

Categories