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

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.

Related

PHP Mysqli database connection pooling to avoid maximum user count

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'));
}

DB2 connection with PDO throws General Error -7008 when Inserting or Deleting

We're developing a PHP application that connects both to a PostgreSQL server and an IBM i server with DB2. While the PDO connection to PGSQL works just fine, the connection to DB2 can only fetch from tables; trying to Insert or Delete results in the following error:
SQLSTATE[HY000]: General error: -7008 (SQLExecute[4294960288] at /build/php7.0-ltLrbJ/php7.0-7.0.33/ext/pdo_odbc/odbc_stmt.c:260)
This error happens both on our development and production environments. Both servers are Ubuntu (different versions, but not by much); I'm using the ODBC driver for PDO.
We tried to connect to other IBM i servers, and with different users, but the exact same problem still arises. Can Select, but not Insert. Googling the error code doesn't yield any useful result, and as you can see the error message itself it's as unhelpful as can be. The code in the SQLExecute particularly doesn't appears anywhere, not even a single result (there is a result from an IBM page, but it's actually a different error code).
The code is pretty simple, but perhaps there is some obvious and glaring error there.
The test script:
include("DB2.php");
$oDAO = new DAO();
$res = $oDAO->ejecuta("INSERT INTO <Library>.<File> VALUES (1,0,1)");
The DAO:
class DAO{
var $link;
public function __construct(){
// función constructora, inicia la conexión
$this->link = new PDO("odbc:DRIVER={IBM i Access ODBC Driver};SYSTEM=<System>;PROTOCOL=TCPIP",
'<user>', '<pass>');
$this->link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
private function begin() { $this->link->beginTransaction(); }
private function rollback() { $this->link->rollBack(); }
private function commit() { $this->link->commit(); }
public function ejecuta($query){
try{
$this->begin();
$oResult = $this->link->query($query);
if($oResult){
$bResult = true;
$this->commit();
}else{
$bResult = false;
$this->rollback();
}
}
catch (Exception $e){
echo $e->getMessage();
$bResult = false;
$this->rollback();
}
return $bResult;
}
}
Frankly, we're out of options and I already wasted two weeks with this. We just need to insert and delete records. So any help is welcome.
The symptoms you describe are consistent with attempting to modify the database under commitment control, but without journaling enabled.
There are three common ways to deal with this:
Turn journaling on. This is pretty extreme, since the folks who administer the database would have to do this, and if they've got journaling turned off, it's likely they either don't really know how to deal with journals, or don't want to. But it's the only practical way to have full commitment control on Db2 for i.
Connect with autocommit on. This will add an implicit commit to any database-modifying SQL statements executed with this connection. In my experience, this is the most common and convenient way to handle the situation.
Add WITH NC to each relevant SQL statement. In principle, this gives you statement-by-statement control over whether to suspend commitment control. In practice, if you are thinking of doing this in the first place, you probably don't have journaling enabled, and thus you will have to do this on each and every database-modifying SQL statement. This is why most people gravitate toward option 2.

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.

Warning: mysql_query(): 7 is not a valid MySQL-Link resource

Similar questions to this my have been asked a lot of times before. But since I did not find a solution in any of the questions asked before me, I take the liberty of asking it again.
My program uses a class made by me which handles all database connections for the program. Several modules I've used before used the same class without fail but when I chose to do a new module using the same class, the warning shows as-
Warning: mysql_query(): 7 is not a valid MySQL-Link resource in wherever... on line 49.
The warning happens when I execute a MySQL query through a function I made. The function is as follows-
public function runquery($_query)
{
$result = mysql_query($_query,$this -> connection); //line 49
if (! $result) die(mysql_error());
else return $result;
}
The function belongs to a class named mysql and it has not been tampered with or made changes to. So the function should technically work as expected, as every other module relying on the same class for database connectivity works just fine.
The query execution is successful however and I manage to update tables with no problems (except the warning). The block of code in the main program where the runquery() function is called from is as follows-
$phpmyadmin = new mysql();
$phpmyadmin->connect('localhost', 'root', '');
$phpmyadmin->setdb('test_db');
$result = $phpmyadmin->runquery($Query);
unset($phpmyadmin);
So the mysql's functions work just as fine as ever and the query executes just fine. But the warning shows for a reason I cannot understand. Any help?
The symptoms suggest that the database connection has been closed or dropped. Look for unwanted mysql_close() calls in your code. Additionally, you can use the following functions to troubleshoot the issue:
is_resource() and get_resource_type() to confirm that $this->connection is a valid data type.
mysql_ping() to find out if the database connection is alive.
If it's a rare issue, log stuff into a file and wait until it happens again.
There should not be spaces.
$result = mysql_query($_query,$this->connection);

Categories