Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP activerecord mysql server has gone away

I'm using php-activerecord for a short while now and i absolutely love it. Php-activerecord is an open source ORM library based on the ActiveRecord pattern. However, i recently tried to use it in combination with a websocket application based on Wrench.

This works perfectly but to start the script the application has to run as a daemon on linux in order to make the websockets always availeble. After a short while of not using the application and then trying to use it again it throws some database exceptions:

At first it gives a warning:

PHP Warning: Error while sending QUERY packet. PID=XXXXX in /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php on line 322

Then it throws a fatal error:

PHP Fatal error: Uncaught exception 'ActiveRecord\DatabaseException' with message 'exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2006 MySQL server has gone away' in /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php:322

Stack trace:

#0 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php(322): PDOStatement->execute(Array)

#1 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Table.php(218): ActiveRecord\Connection->query('SELECT * FROM ...', Array)

#2 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Table.php(209): ActiveRecord\Table->find_by_sql('SELECT * FROM `...', Array, false, NULL)

#3 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Model.php(1567): ActiveRecord\Table->find(Array)

#4 in /home/user/domains/example.com/public_html/vendor/php-activerecord/lib/Connection.php on line 325

It seems like php-activerecord is keeping the mysql connection open all the time that the websocket server is running, this ofcourse should not be a problem if it then automatically tried to reconnect and run the query again. But it doens't.

I've read something about setting MYSQL_OPT_RECONNECT. But i'm not sure if that works or how to set that option using php-activerecord. Does anybody here have some experience in this area?

Edit: Here are my global timeout config variables

VARIABLE_NAME                   VARIABLE_VALUE  
DELAYED_INSERT_TIMEOUT          300
WAIT_TIMEOUT                    28800
CONNECT_TIMEOUT                 10
LOCK_WAIT_TIMEOUT               31536000
INNODB_ROLLBACK_ON_TIMEOUT      OFF
THREAD_POOL_IDLE_TIMEOUT        60
NET_WRITE_TIMEOUT               60
INNODB_LOCK_WAIT_TIMEOUT        50
INTERACTIVE_TIMEOUT             28800
DEADLOCK_TIMEOUT_LONG           50000000
SLAVE_NET_TIMEOUT               3600
DEADLOCK_TIMEOUT_SHORT          10000
NET_READ_TIMEOUT                30
like image 261
RTB Avatar asked Apr 14 '15 18:04

RTB


4 Answers

PHP ActiveRecord uses PDO. There is absolutely no way to close a PDO connection, it is the wrong DB layer for long running background tasks.

You can try to influence the disconnection of a PDO connection with the following snippet.

//if not using ZF2 libraries, disconnect in some other way
$db->getDriver()->getConnection()->disconnect()
$db = NULL;
gc_collect_cycles();

Disconnect, set your reference to null, then run the garbage collector. The hope is that that will call the PDO's internal __destruct method to actually close the connection.

You must manage your DB connections in your own long running script. You must disconnect if your worker hasn't had to process work in a while, and you must reconnect when you have work.

The real solution is to not use PDO and disconnect and reconnect normally.

If you simply set both server and client library timeouts to be infinite, you'll run into problems with out of control scripts that never die, forcing you to restart the entire server (not a good idea to mess with timeouts).

EDIT: I actually had this exact problem and used this exact solution at work last year. This solved 99% of my problems. But still, every once in a while there wass a stray connection exception that I could not catch and try to reconnect. I simply restart the processes once a day to rid myself of those stray connection errors. That's why my answer is, don't use PDO. Switch now and get real control over disconnects and reconnects.

like image 141
chugadie Avatar answered Nov 20 '22 16:11

chugadie


The most common reason for the MySQL server has gone away error is that the server timed out and closed the connection.

Try doing the following change.

max_allowed_packet=64M

If you have a lot of request set this and don't set it to bigger because its related with your environment.

max_connections=1000

Adding this line into my.cnf file might solves your problem. Restart the MySQL service once you are done with the change.

Read more on MySQL server has gone away

If it does not work try this auto-reconnect function as well.

like image 33
Techie Avatar answered Nov 20 '22 17:11

Techie


As said, MySQL in PHP scripts times out when there is no communication between the two for some time. That is a good thing, since idle connections would eat up your server resources.

"Server has gone away" error mostly happens when a relatively lenghty computation happens between two queries.

In order to prevent that, you can

  • Periodically execute a SELECT 1 query during your execution
  • Create a wrapper around your queries which checks if connection is valid before executing
  • Use answer from this post

However, I believe that reconfiguring MySQL to keep connection open for longer encourages careless programming and would advice against it.

like image 1
Ivan Batić Avatar answered Nov 20 '22 18:11

Ivan Batić


It could be also the size of the query, as sometimes ORMs combine the queries to improve performance.

Try setting max_allowed_packet=128M, at least should be useful as a diagnose.

like image 1
appartisan Avatar answered Nov 20 '22 18:11

appartisan