PHP Mysqli database connection pooling to avoid maximum user count - php

I surfed on Internet for past two days to create the DB pooling by PHP, but not yet achieved. I'm using PHP and MySQLi. We bought the mysqli db with 15 Maximum user connection. I want to pool the db connection to avoid the new connection. I used persistent as well as mysqli_connect. but I don't feel much different both are creating the new connection since other user already logged in. I was trying this function to get DB connection.
<?php
function getConnection(){
if ($connect){
return $connect;
}else{
$connect = new mysqli('p:xxxx','yyy','zzz','aaaa');
return $connect;
if(mysqli_connect_errno($connect))
{
echo "Server Busy";
}
}
}
?>
But above function only returns the else part. Please suggest me how to handle this. Thanks in advance. For now I'm killing the process which are in sleep mode to reduce the probability of increasing DB connection.

There is no connection pooling in PHP.
The persistent connection you are trying to use (that "p:" bit) is the most sure way to hit the maximum connection number, so get rid of it immediately.
15 concurrent connections is, actually, A LOT. Simply optimize your queries, so a typical connection would last 0.1 second, which would mean 150 concurrently executed PHP scripts which is like 1500 users on-line.
Also, you need to add
static $connect;
as the first line in your function, or is will create the new connection every time it is called, which is the actual reason why you are getting this error.
<?php
function getConnection(){
static $connect;
if (!$connect){
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$connect = new mysqli('xxxx','yyy','zzz','aaaa');
$connect->set_charset('utf8mb4');
}
return $connect;
}
Better yet, get rid of this function at all, have a separate file with the mysql connection code, and then use the $connect variable all around your code. See my article about mysqli connect for the details.

This is not how it works. See here. MySQLi will select one of available connections when you execute new mysqli('p:... The connection is persistent, not the PHP object.
function getConnection(){
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
return (new mysqli('p:xxxx','yyy','zzz','aaaa'));
}

Related

mysqli_insert_id() is returning 0 but inserting the data

The Code is:
class anything_i
{
/*Every variable is defined and hidden fro privacy.*/
public function connect(){
return mysqli_connect(self::HOST,self::USERNAME,self::PASSWORD,self::DATBASE);
}
public function insertData($postData){
$sqli = 'INSERT INTO `payments`(`item_name`,`price`,`email`,`date`,`time`,`detail`,`volume`,`ip`,`payment_status`) VALUES ("'.$productData['name'].'","'.$productData['price'].'","'.$postData['email'].'","'.$date.'","'.$time.'","'.$postData['list'].'","'.$productData['volume'].'","'.$ip.'","On Hold")';
if(mysqli_query($this->connect(),$sqli)){
print_r(mysqli_insert_id($this->connect()));
}else{
print_r(mysqli_error($this->connect()));
}
}
}
It is inserting the data and working fine but does not return anything other than a 0 (zero) not getting any error.
Let me clear that my table contains auto_increment and my connection is fine because it is entering data just fine. Please don't disregard the question because you found similar once answered. I also found similar questions but most of them have connection problems, some of them the no AUTO_INCREMENT column and there may be some which included another query in between. So, please read it before mentioning another answer.
Here is the proof of AUTO_INCREMENT:
I suspect this code has been migrated from the legacy mysql extension where mysql_connect():
Opens or reuses a connection to a MySQL server.
This is no longer the case with mysqli_connect():
Opens a connection to the MySQL Server.
You really need to store the connection in a variable and reuse that same connection. Currently you're starting many different connections within the same script run.
When you call mysqli_connect() it will create a new connection each time. It does not reuse the previous connection. When a new connection is created all the properties of the old one are lost.
You are calling mysqli_connect() every time you call $this->connect() so you will never get the errors or the auto-generated ID.
mysqli connection should be global to your application. It does not make sense to keep recreating the same connection because it will lead to terrible performance issues and it will cause you problems like this one. If you are using dependency injection it should be easy to create the mysqli at the start of your application and then pass it as an argument to your class' constructor.
Connecting to the database using mysqli is always the same 3 lines of code. Only the details you pass as arguments are different.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'db_name');
$mysqli->set_charset('utf8mb4'); // always set the charset
You can then pass this to your constructor whenever you create an object and store it in a private property.
Your fixed code would like this:
<?php
class anything_i {
private mysqli $db = null;
public function connect(mysqli $db) {
$this->db = $db;
}
public function insertData($postData) {
/*
...
*/
$stmt = $this->db->prepare('INSERT INTO `payments`(`item_name`,`price`,`email`,`date`,`time`,`detail`,`volume`,`ip`,`payment_status`) VALUES (?,?,?,?,?,?,?,"On Hold")');
$stmt->bind_param('ssssssss', $productData['name'], $productData['price'], $postData['email'], $date, $time, $postData['list'], $productData['volume'], $ip);
$stmt->execute();
}
}
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'inet', '5432', 'test');
$mysqli->set_charset('utf8mb4'); // always set the charset
$obj = new anything_i($mysqli);

How reconnect and retry a MySQL query in PHP when the database connection has been lost?

I have a PHP file which sometimes has a long execution and the MySQL connection (a mysqli object) goes stale. If I check the connection with mysqli_ping (and reconnect if mysqli_ping returns false), then I never have a problem. However, pinging before every query seems highly inefficient, so I'd like to only perform the ping check (and reconnect) upon the query failing. My problem is that I cannot seem to get my code to throw an exception upon the failure of the mysqli_query in order to trigger a reconnect.
Here is my "basic" code:
<?php
function query($query) {
$connection = $GLOBALS['global_connection'];
if(empty($connection) || mysqli_connect_errno()) $connection = connect();
try {
$result = mysqli_query($connection, $query);
} catch(Exception $e) {
if(!mysqli_ping($connection)) {
$connection = connect(); // reestablish the connection
$GLOBALS['global_connection'] = $connection; // update global connection value
$result = mysqli_query($connection, $query); // requery using the new connection
}
}
return $result;
}
The problem is that a bad connection in the mysqli_query does not cause an exception to be thrown, but it does cause an error to show up in my error log.
I have tried mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); (as suggested in other questions) before the mysqli_query but it does not change the outcome. I also have mysqli.reconnect enabled in my PHP config, but that doesn't seem to stop this.
So my question is either:
How do I throw an exception when a mysqli_query fails (due to a timed out connection)?
or
How do I automatically reconnect database in an efficient manner?
Per Barmar's help in the comments I realized all I had to do was this:
<?php
$result = mysqli_query($connection, $query);
if(empty($result)) {
if(!mysqli_ping($connection)) {
$connection = connect(); // re-establish the connection
$GLOBALS['global_connection'] = $connection; // update global connection value
$result = mysqli_query($connection, $query); // re-query using the new connection
}
}
No try{}catch needed at all! Clean and simple.
You will need to manage (throw) your own custom exceptions for this to work the way you need it too. I would consider making a database abstraction class to help handle this. The database class would have a member variable that is the connection reference and could use the mysqli built in error handling to throw custom exceptions relating to that instance of the mysqli connection object.
If you only need one database connection I might try a singleton pattern.

Overwriting an object closes the DB connection?

We're getting an error from the server saying that there are to many DB connection to the DB. I'm trying to locate the logic which causes the lack of optimization. We connect to the DB using an object called DB_Con. This object creates the connection on init.
My question is if
$Con = new DB_Con
would
$Con = null
close the connection? If so is it done right away or is it slated for garbage collection at a later time.
Also, would the following two lines of code open two DB connections or one?
$Con = new DB_Con
$Con = new DB_Con
You should only really have 1 DB Connection open per execution.
When you're done with the DB use $mysqli->close();
It's even noted on the close page that unless you explicitly close a connection the connection will not close.

How do I check the DB connection

I have host, database name, username and the password given as form inputs like:
$form['dbname']->getData()
I need to check if these data is correct for the mysql connection. So I chose to use mysql_connect() to check this:
$conn = mysql_connect($form['host']->getData(), $form['username']->getData(), $form['password']->getData(), $form['dbname']->getData());
if($conn) // ...
else // ...
But it displays some mysql_connect() warning with no other specific message...
What's wrong? Does the symfony 2 has any mechanism to check the connection?
Symfony uses repositories and entities to manage the database. The programmer doesn't manipulate the connection itself (Doctrine).
You could try to check a connection using PDO. Try to instance a PDO Object, and catch exceptions (PDOException for connection errors). However, you're "breaking" the framework's philosophy, trying to initiate an "extern" DB connection. If you need to work with several connections in Symfony, I suggest this reference :
http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html
use the following format to receive the connection error if there is any.
$con = mysql_query() or die(mysql_error());

how to enable database auto-reconnect in PHP? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
and the database is MYSQL
Sometimes when your MySQL connection opened for too long, the connection to the DB will be dropped when the time without a query exceeds the wait_timeout value in my.cnf. You will get "MySQL server has gone away" timeout error.
This is how I implement auto reconnect in my code:
class databaseClass {
var $conn;
var $db;
public function __construct() {
$this->connect();
}
public function connect() {
$this->conn = mysql_connect(DB_HOST, DB_USER, DB_PASS);
$this->db = mysql_select_db(DB_NAME, $this->conn);
}
public function disconnect() {
mysql_close($this->conn);
}
public function reconnect() {
$this->disconnect();
$this->connect();
}
public function queryCompanyExist($company) {
//auto reconnect if MySQL server has gone away
if (!mysql_ping($this->conn)) $this->reconnect();
$query = "SELECT name FROM company WHERE name='$company'";
$result = mysql_query($query);
if (!$result) print mysql_error() . "\r\n";
return mysql_fetch_assoc($result);
}
}
Refer here for more infomation about mysql_ping
From the C mysql API:
my_bool reconnect = 0;
mysql_options(&mysql, MYSQL_OPT_RECONNECT, &reconnect);
See http://dev.mysql.com/doc/refman/5.6/en/auto-reconnect.html
From PHP mysqli in php.ini set the global:
mysqli.reconnect = On
See http://www.php.net/manual/en/mysqli.configuration.php#ini.mysqli.reconnect
For the PHP PDO mysql driver it should be available through PDO::setAttribute but I am unable to find documentation indicating that it is implemented. The code appears to be attempting to respect the MYSQL_OPT_RECONNECT which is now required by mysql but to have failed to do so in the initial implementation (https://bugs.php.net/bug.php?id=58863). The intent of the patch in 58863 is to allow:
new PDO('mysql:host=xxx', 'xx', 'xx',array(PDO::MYSQL_OPT_RECONNECT=>true));
The reasons why the reconnect occurs are various but commonly because a pooled set of connections contains a mature connection which has timed out due to a lack of use. By default mysql connections time out after 8 hours. See: http://dev.mysql.com/doc/refman/5.6/en/gone-away.html
For side effects of a reconnection see: http://dev.mysql.com/doc/refman/5.6/en/auto-reconnect.html
You can use the mysql_ping() function to test the status of the connection and reconnect when it returns false. mysql_ping() will even reconnect for you if you're using a MySQL before 5.0.13 as mentioned on that documentation page; "Since MySQL 5.0.13, automatic reconnection feature is disabled.".
You can write a function which will ping the database via connection and in case it down, reconnect it again and then proceed the query or whatever you want, also take a look on mysqli php library, it can be useful for you.
PS. Also could be useful to implement Singleton design pattern in order to maintain the database connection, once created it will connect to database and then you can implement the method called getConnection which each time will proceed with the check I've described above.
PPS. You can use an exception, try you query, whenever it fails catch an exception, reconnect and try again.
You should be checking if the query fails anyway. By checking the error code you can tell if it failed because of no connection and reconnect. Just make sure you keep track of reconnection attempts so you don't get stuck in a loop.
Why do you need to "reconnect" in the first place? How/Why are you getting disconnected? In PHP you connect at the beginning of the script and the connection is closed automatically at the end of the script.
There's no need to call mysql_close in your script at all (and it would be silly to "automatically reconnect" if you explicitly closed the connection).
You can try mysql_pconnect is that's what you're looking for. The connection will then stay open permanently, and other scripts that connect can use the connection.

Categories