php mysql activerecord phpactiverecord wrench

El servidor de PHP activerecord mysql se ha ido



phpactiverecord wrench (6)

La razón más común para que el servidor MySQL se haya ido es que el servidor ha agotado el tiempo de espera y ha cerrado la conexión.

Intenta hacer el siguiente cambio.

max_allowed_packet=64M

Si tiene una gran cantidad de solicitudes, configúrelo y no lo configure en mayor porque está relacionado con su entorno.

max_connections=1000

Agregar esta línea en my.cnf archivo my.cnf podría resolver su problema. Reinicie el servicio MySQL una vez que haya terminado con el cambio.

Leer más en el servidor MySQL se ha ido

Si no funciona, intente también con esta función de reconexión automática.

Estoy usando php-activerecord por un tiempo corto y me encanta. Php-activerecord es una biblioteca ORM de código abierto basada en el patrón ActiveRecord . Sin embargo, recientemente traté de usarlo en combinación con una aplicación websocket basada en Wrench .

Esto funciona a la perfección, pero para iniciar el script, la aplicación debe ejecutarse como daemon en Linux para que los websockets siempre estén disponibles. Después de un momento de no usar la aplicación y luego tratar de usarla de nuevo, arroja algunas excepciones a la base de datos:

Al principio da una advertencia:

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

Entonces arroja un error fatal:

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

Parece que php-activerecord mantiene la conexión mysql abierta todo el tiempo que el servidor websocket se está ejecutando, esto por supuesto no debería ser un problema si luego automáticamente intenta reconectar y ejecutar la consulta nuevamente. Pero no lo hace.

He leído algo sobre la configuración de MYSQL_OPT_RECONNECT . Pero no estoy seguro si eso funciona o cómo configurar esa opción usando php-activerecord. ¿Alguien aquí tiene alguna experiencia en esta área?

Editar: Aquí están mis variables de configuración de tiempo de espera global

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


Para resolver ese problema, te sugiero que:

  1. Distribuya sus procesos utilizando el servidor de trabajos de Gearman ( http://gearman.org/ )
  2. Administre esos procesos fácilmente usando Supervisor ( http://supervisord.org/ )

Aquí es cómo.

Ejecute su aplicación de socket web como daemon, tal como lo hizo ahora (quizás usando cron). O mejor aún, adminístrelo usando Supervisor. Configúrelo para que el Supervisor lo inicie cuando el Supervisor se inicie y vuelva a iniciar automáticamente el daemon si muere.

Ejemplo de configuración:

[program:my-daemon] command=/usr/bin/php /path/to/your/daemon/script autostart=true autorestart=true

A continuación, en lugar de ejecutar el procesamiento de consultas dentro del daemon de la aplicación, cree un Worker Gearman para manejarlo. Una vez registrado, el Trabajador estará esperando ser ejecutado / llamado. Debe llamar al Trabajador desde su aplicación websocket, junto con el parámetro de carga de trabajo necesario si es necesario (consulte el sitio web de Gearman para obtener la explicación de este plazo de carga de trabajo).

En Worker, configúrelo para que pare / salga cuando ya finalice el trabajo solicitado por el daemon. Con esto, no tendrás el problema de que "el servidor mysql se ha ido" porque la conexión se cierra inmediatamente.

Finalmente, tenemos que hacer que el Worker esté disponible todo el tiempo como el daemon. Por lo tanto, similar al daemon, configure Supervisor para que arranque automáticamente y lo inicie de nuevo cuando el Worker muera / pare, así:

[program:my-worker] command=/usr/bin/php /path/to/your/worker/script autostart=true autorestart=true

Otra cosa interesante es que puedes agregar tantos trabajadores como quieras para estar vivo esperando. Simplemente agregue la siguiente configuración:

numprocs=9 #change it to any number process_name=%(program_name)s_%(process_num)02d #to identity worker number

Como le pedimos a Supervisor que reinicie cada proceso, siempre tenemos trabajadores constantes ejecutándose en segundo plano.

Aquí hay otra explicación sobre esta estrategia: http://www.masnun.com/2011/11/02/gearman-php-and-supervisor-processing-background-jobs-with-sanity.html

¡Espero que ayude!


También podría ser el tamaño de la consulta, ya que a veces los ORM combinan las consultas para mejorar el rendimiento.

Intenta establecer max_allowed_packet = 128M, al menos debería ser útil como diagnóstico.


PHP ActiveRecord usa PDO. No hay absolutamente ninguna forma de cerrar una conexión PDO, es la capa DB incorrecta para las tareas en segundo plano de larga ejecución.

Puede intentar influir en la desconexión de una conexión PDO con el siguiente fragmento.

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

Desconecte, establezca su referencia a nulo, luego ejecute el recolector de basura. La esperanza es que eso llame al método __destructivo interno de la PDO para cerrar realmente la conexión.

Debe administrar sus conexiones de base de datos en su propio script de ejecución larga. Debe desconectarse si su trabajador no ha tenido que procesar el trabajo por un tiempo, y debe reconectarse cuando tenga trabajo.

La verdadera solución es no usar PDO y desconectarse y reconectarse normalmente.

Si simplemente establece que los tiempos de espera de la biblioteca del servidor y del cliente sean infinitos, se encontrará con problemas con secuencias de comandos fuera de control que nunca se mueren, lo que le obligará a reiniciar todo el servidor (no es una buena idea interferir con los tiempos de espera).

EDITAR: En realidad, tuve este problema exacto y utilicé esta solución exacta el año pasado. Esto resolvió el 99% de mis problemas. Pero aún así, de vez en cuando había una excepción de conexión extraviada que no podía detectar e intentar reconectar. Simplemente reinicio los procesos una vez al día para deshacerme de esos errores de conexión parásitos. Es por eso que mi respuesta es, no use PDO. Cambie ahora y obtenga un control real sobre las desconexiones y reconectaciones.


Si su base de datos no está manejando múltiples conexiones concurrentes y consultas, puede establecer tiempos de espera "infinitos". Esto no afectará significativamente los recursos de DB. El mejor enfoque es enviar paquetes de ping (SELECT 1) para renovar el tiempo de espera y hacer que la conexión se mantenga activa.


Como se dijo, MySQL en scripts PHP agota el tiempo cuando no hay comunicación entre los dos por algún tiempo. Eso es bueno, ya que las conexiones inactivas consumirían los recursos de tu servidor.

El error "El servidor se ha ido" ocurre principalmente cuando se produce un cálculo relativamente largo entre dos consultas.

Para evitar eso, puedes

  • Ejecute periódicamente una consulta SELECT 1 durante su ejecución
  • Cree un contenedor alrededor de sus consultas que compruebe si la conexión es válida antes de ejecutar
  • Usa la respuesta de esta publicación

Sin embargo, creo que la reconfiguración de MySQL para mantener la conexión abierta durante más tiempo fomenta la programación descuidada y aconsejaría en contra de ella.