PHP PDO Exception + Warning on MySQL Has Gone Away? - php

We are getting both a PDOException and warnings. These warnings are driving us crazy.
Warning: PDOStatement::execute(): MySQL server has gone away in /home/Database.php on line 120
Warning: PDOStatement::execute(): Error reading result set's header in /home/Database.php on line 120
Here is the code that does this -- this is just to simulate a connection going away:
$db = new PDO('mysql:dbname=' . $name . ';host=' . $host, $user, $pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$statement = $db->prepare('SET SESSION wait_timeout = 1');
$statement->execute();
sleep(3);
try {
$statement = $db->prepare('SELECT 1');
$statement->execute();
} catch (PDOException $e) {
echo 'Exception! Err #:' . $e->errorInfo[1] . PHP_EOL;
}
EDIT: The question is why does this generate a warning and an exception. The code above just generates both even though we specifically tell PDO to throw exceptions.
The code above makes it happen faster than waiting for our servers default wait_timeout.
EDIT 2: I'm not sure why this was closed. The question is WHY is PHP spawning both a Warning, and an Exception regardless of the PDO Error Level?

You set wait_timeout to 1 then you sleep 3, what will happen? MySql will close connection after one second and you will get error "Mysql Server has gone away" with next statement 'cause you sleep for 3.
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout
edit
Question is duplicate of MySQL error 2006: mysql server has gone away
edit 2
Causes of this error:
low wait_timeout - solution: ping, reconnect or increase it too
large packets - solution: tune max_allowed_packet in my.cfg
PDO reconnect - simulate ping in PDO How do i ping the MySQL db and reconnect using PDO
edit 3 question updated
The only way (afaik) to get rid of these warnings is to set expected (eg. E_ERROR) error_reporting level. You could wrapped pdo calls up in for example to set E_ERROR before and reset to default after execution.
PDO logs warnings/errors for logs purposes (sic!) for further analytics. The attribute you set (by setAttribute or constructor) only changes error handling/behavior of pdo - throw or not:). These two things are separated.

To prevent this error I'd just add
$db->setAttribute(PDO::ATTR_TIMEOUT,ini_get('max_execution_time'));
to your ->setAttribute calls after creating the PDO object.
I don't really know if this really works, but it should work.
(didn't test it)

Related

Is there a way to set max_allowed_packet in PDO using PHP?

I ran across
PHP Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
And I was looking for a way to change both the timeout and the max_allowed_packet without modifying the config files nor restarting the server. I found the first one had a PDO ATTRIBUTE called ATTR_TIMEOUT, but I haven't been able to find the attribute for the size, the only thing I managed to find was a MYSQL_ATTR_MAX_BUFFER_SIZE which seems to be deprecated. Is there any other way or attribute I could use for this?
And before anyone asks: I simply can't modify the config files.
This is the full code for the connection including the deprecated attribute:
try {
$conn = new PDO('mysql:host=host;dbname=dbname','','');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$conn->setAttribute(PDO::ATTR_TIMEOUT, 360);
$conn->setAttribute(PDO::MYSQL_ATTR_MAX_BUFFER_SIZE, 1024*1024*10);
}catch(PDOException $e){
echo "ERROR ACCOUNTING: " . $e->getMessage();
}

how to conect to secondary database if primary database is down (PHP)

i hope someone can help me, ive been struggling on this for 3 days now.
here is my situation, i am making a website with php, and i have 2 computers as servers with wampserver...
main server is 192.168.0.10
secondary server is 192.168.0.12
and a virtual machine where im trying out if the remote conection works
my website is hosted on my main server so the conexion query is...
$conexion = mysqli_connect("localhost","root","","dbdaq");
it works fine, i even have master to master replication on the servers.
but what i need to do is that when main server is down it needs to try to conect to the database on the seondary database, so im trying to use the code...
$conexion = mysqli_connect("localhost","root","","dbdaq");
if (!$conexion){
$conexion = mysqli_connect("192.168.0.12","root","password","dbdaq");
}
but when i manually turn of the mysql services on main server it doesnt actually try to use the other servers database...
it keeps giving me the error that says
Warning: mysqli_connect(): (HY000/2002): No connection could be made because the target machine actively refused it. in C:\wamp64\www\PaginaV2\Pagina\PHP y JS\Procesoalumno.php on line 2
Using # to suppress error messages is a bad idea, and a bad practice. A better solution is to set mysqli to throw exceptions on failure, and catch the exception.
You can set mysqli to throw exceptions by adding the following line before you make your connection(s).
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
Using exceptions over suppressing the error, you can extract the relevant error-message and error-code if you need them for specific handling or logging, in a much cleaner way than you can with suppressing the errors.
Though it might look like its more complex, the reason for this is that we also test the second connection (which you should do anyways, regardless how you do it) - and we test the second connection the same way we test the first connection, by a second try/catch inside the first catch block.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // errors in MySQLi now throws exceptions
try {
$conexion = mysqli_connect("localhost","root","","dbdaq");
} catch (Exception $e) {
try {
$conexion = mysqli_connect("192.168.0.12","root","password","dbdaq");
} catch (Exception $e) {
echo "Connecting to both databases failed";
exit;
}
}
Try this: use php's # operator (the error control operator) to suppress the error message from the first connection failure. Try this.
$conexion = #mysqli_connect("localhost","root","","dbdaq");
if ( !$conexion ) {
$conexion = mysqli_connect("192.168.0.12","root","password","dbdaq");
}
It seems likely your code for the failover connection works correctly, but you still get an obnoxious error message. The # operator suppresses the message.

mysql_query() expects parameter 2 to be resource error in connection with remote mysql DB

My PHP code works well in connecting remote windows system mysql database and returns the output. But, when I'm using the same to connect remote linux system's mysql database, I got the following error:
"mysql_query() expects parameter 2 to be resource, boolean given in
C:\wamp\www\mysqldb.php on line 88"
That line 88 have the following content "$this->resultQur =
mysql_query($query, $this->connID);"
Help me to solve this.
yes. The resource is null in this case. But the same works in windows mysql connection. I got the error only in linux. Need to do any change for linux environment?
While putting "print mysql_error();" i got the following error
"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond."
The resource you're providing comes from a mysql_connect and that did not succeed!
Put error reporting on
Build some basic error handling in your script
Do not use mysql_* but mysqli_* or even better PDO with parameter binding
Output returned string from mysql_error() after your query. In that way you will see actual error.
$this->resultQur = mysql_query($query, $this->connID);
print mysql_error();
mysql_connect returns a resource on success, but a boolean "false" on error.
Your connection attempt probably failed an so the mysql_query won't be successful.
Try something like the following to see what exactly is causing the error.
mysql_connect(..) or die(mysql_error());
Additionally, it seems that the "old" mysql-library get's deprecated in PHP and it's recommended to switch to a more modern version, eg mysqli or PDO.
1 . Firstly put ini_set(‘display_errors’,1);error_reporting(E_ALL|E_STRICT); in your code at the start of the page
2 . Put Try catch around the query and print the Exception message
try { enter code here }catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
3 . Use PDO then the mysql object for query it's a modern and better approach
Use try catch around the the query and try

mysql Link to server lost, unable to reconnect

I get the following error:
Link to server lost, unable to reconnect
I have a mysql daemon coded, and I use mysql_pconnect to connect to mysql but after a while, I get the following error and the daemon stops functioning properly:
Link to server lost, unable to reconnect
What I do is the following:
while(true)
{
$connect = mysql_pconnect(...);
$db = mysql_select_db(...);
}
What can I do to prevent this? I need mysql connection to stay steady for the whole duration of the daemon - which may be forever.
You have a few choices.
But just as a precursor, you should try and move away from relying on mysql_* and start using the PDO instead.
Anyway...
When you open a mysql connection, it will stay "available" until the wait timeout has expired. What you are doing is constantly creating a new connection, (also without closing the other connection). This means you will either hit the server mysql limit, or your unix box socket limit very quickly.
Wait Timeout
You should first check with your server to see what this timeout is set to.
You might want to consider increasing it in your my.cnf if it is terribly low. The default period is 28800 seconds (if I recall correctly).
You can check by issuing this query:
SHOW variables like "%wait_timeout%"
You can then change the value in your my.cnf to increase it or you can also set it using
SET ##GLOBAL.wait_timeout=288000
SELECT 1
Okay, now, with a reasonable set timeout set, the "typical" way that you can make sure that you don't get the mysql has gone away message, is to just do a SELECT 1. This will do another query and make sure that the connection is held open.
And, the benefit of using the PDO is that you can then catch PDOExceptions which might be thrown when a SELECT 1 fails.
This means, that you can then try and connect again, if an exception is thrown, and then check again. If you can't connect after that then you should probably kill your daemon.
Here is some code.... you would clearly have to make your PDO object using a valid connection string.
// $pdo holds the connection and a PDO object.
try {
$pdo->execute("SELECT 1");
} catch (PDOException $e) {
// Mysql has gone away.
$pdo = null
$pdo = new PDO( $connectionString );
echo "Mysql has gone away - But we attempted to reconnect\n";
try {
$pdo->execute("SELECT 1");
} catch (PDOException $e) {
echo "Mysql has failed twice - Kill Daemon\n";
throw($e);
}
}
This is the solution that I would probably take.
You can easily substitute the SELECT 1 with your own query that you actually want to use. This is just an example.

PHP Error handling in WordPress plugin

I am a newbie to both PHP and Wordpress (but do ok in C#), and am struggling to understand the error handling in a custom plugin I am attempting to write. The basics of the plugin is to query an exsiting MSSQL database (note its not the standard MYSQL db...) and return the rows back to the screen. This was working well, but the hosting provider has taken my database offline, which led me to the error handling problem (which I thought was ok).
The following code is failing to connect to the database (as expected), but puts an error onto the screen and stops the page processing. It does not even output the 'or die' error text.
QUESTION: How can I just output a simple "Cant load data" message, and continue on normally?
function generateData()
{
global $post;
if ("$post->post_title" == "Home")
{
try
{
$myServer = "<servername>";
$myUser = "<username>";
$myPass = "<password>";
$myDB = "<dbName>";
//connection to the database
$dbhandle = mssql_connect($myServer, $myUser, $myPass)
or die("Couldn't open database $myDB");
//... query processing here...
}
catch (Exception $e)
{
echo "Cannot load data<br />";
}
}
return $content;
}
Error being generated: (line 31 is $dbhandle = mssql_connect...)
Warning: mssql_connect() [function.mssql-connect]: Unable to connect to server: <servername> in <file path> on line 31
Fatal error: Maximum execution time of 30 seconds exceeded in <file path> on line 31
First of all, if mssql_connect raises a warning when there's a problem, there is not much you can do to avoid it : the only thing you could do is hide it, using the # operator :
if (($dbhandle = #mssql_connect($myServer, $myUser, $myPass)) === false) {
// connection failed
}
Note : you should not die() when a connection error occurs : it'll stop the execution of the whole application, which is most certainly not desired.
The Fatal Error is a second problem (which is probably a consequence of the first one).
Note that you cannot recover from a Fatal Error : it is Fatal. Which means you must avoid it, one way or another.
Here, the error is that your script is working for more than max_execution_time seconds ; as the error is reported on the mssql_connect line, I suppose the script is waiting for the connection to succeed, and it doesn't get etablished in less that 30 seconds.
I don't have an SQL Server database to test, but looking at the Runtime Configuration section of the manual for mssql, I'd say that these look interesting :
name Default value
mssql.connect_timeout "5"
mssql.timeout "60"
You could try changing those,
either in your php.ini file, if you can modify it
or using ini_set() before trying to connect.
In the second case, something like this might do the trick :
ini_set('mssql.connect_timeout', '3');
ini_set('mssql.timeout', '3');
You may also want to look at WP_Error Class for handling your errors in an elegant manner. Note that this is a generic approach & that you will have to handle the particular error detection logic separately. WP_Error will help you in gathering all the errors in one place.

Categories