2010-11-23 14 views
8

Sé que hay muchas preguntas similares aquí, también hay muchos resultados cuando lo googleo, pero ninguno de ellos responde mi pregunta. Leo this, this, this y this, pero ninguno de ellos funciona para mí. No hablo de bloqueos, no quiero hacer esto usando el conector C++ de MySQL, solo la API C.Cómo establecer un tiempo de espera para la consulta de MySQL con C API

Además, lo que es muy importante aquí: lo hago en LINUX. ¿Por qué menciono esto? Debido a que en la documentación de mysql_options:

MYSQL_OPT_READ_TIMEOUT - ...This option works only for 
TCP/IP connections and, prior to MySQL 5.0.25, only for Windows. 

MYSQL_OPT_WRITE_TIMEOUT- ... This option works only for 
TCP/IP connections and, prior to MySQL 5.0.25, only for Windows

Así que, ¿hay alguna manera de establecer un tiempo de espera de consulta para las versiones, antes 5.0.25?

Mi versión de MySQL:

[[email protected] kiril]# mysql --version 
mysql Ver 14.12 Distrib 5.0.22, for redhat-linux-gnu (i686) using readline 5.0

EDIT: Al menos, ¿hay alguna forma de cancelar una consulta? Puedo iniciar un temporizador como un hilo diferente, pero cuando expire ... ¿puedo cancelar la consulta de alguna manera?

+0

¿Qué versión de MySQL está utilizando? – SubniC

+1

@Kiril Kirov - Puede usar el comando kill en mysql para matar una consulta en ejecución - http://dev.mysql.com/doc/refman/5.0/en/kill.html – ajreal

+0

@ajreal - ¡Gracias! Voy a intentarlo –

Respuesta

2

Bien, encontré una solución .. Gracias a Will y PRR (mi compañero de trabajo).

I no puedo un hilo nuevo en cada consulta, ya que es una aplicación en tiempo real, que se supone que procesar 1000+ mensajes por segundo .. (todos modos, gracias a la idea de R..).

Además, no fue posible para terminar la conexión a través de la biblioteca, ni para cancelar/matar a la consulta, ya que el problema estaba en el servidor de base de datos ..

Y he aquí una solución de fuerza bruta, pero aún mucho mejor que _EXIT(FAILURE): Aquí está la pregunta relacionada: "How to force closing socket on Linux?" - entonces, acabo de cerrar el socket usando una llamada al sistema.

NOTA IMPORTANTE: (gracias Will) - Resultó que nuestro contenedor de la biblioteca MySQL tiene el indicador "a prueba de fallas", de modo que en el socket cerrado (u otro error crítico), intenta "resolver" el problema, por lo que vuelve a abrir el socket, por sí mismo, en mi caso. Por lo tanto, acabo de desactivar esta opción y todo está bien ahora - la ejecución se termina debido a una excepción - esta es la forma más "suave" de hacer esto.
Esto debe hacerse a través de otro hilo, por supuesto, un temporizador, por ejemplo.

EDIT: Los tiempos de espera realmente funcionan para las versiones posteriores a la 5.0.25. Pero, al menos en RHEL4 y RHEL5, ¡los tiempos de espera se triplican por alguna razón! Por ejemplo, si algunos de los tiempos de espera se establece en 20 segundos, el tiempo de espera real es ~ 60 seg ..
También, otra cosa importante es, que pueden establecer estos tiempos de espera (como cualquier otra opción) MUSTdespuésmysql_init y antes demysql_connect o mysql_real_connect.

+1

Desde el MYSQL_OPT_READ_TIMEOUT_DOCS: "El tiempo de espera en segundos para cada intento de lectura desde el servidor. Hay reintentos si es necesario, por lo que el valor de tiempo de espera total efectivo es tres veces el valor de la opción." Es por eso que el intervalo real es 3 veces se acabó el tiempo. – jssebastian

0

Nunca he intentado hacer eso, pero he estado leyendo y creo que eso podría significar que MYSQL_OPT_WRITE_TIMEOUT y MYSQL_OPT_READ_TIMEOUT son solo para Windows anteriores a la versión 5.0.25 de MySQL pero que ahora podrían funcionar para cada conexión TCP/IP. Tome un look here

Saludos

EDIT: me gustaría tratar de actualizar mi servidor MySQL a una versión más nueva y probar si funciona.

+0

Por favor, ponga arriba en los comentarios, OP ha declarado claramente su pregunta – ajreal

+0

Lo único que esta publicación (el enlace) dice es una cita de la documentación, la exacta que publiqué en mi publicación. –

+0

Lo siento, hice mi mejor esfuerzo en este asunto. – SubniC

1

Supongo que podría implementar un tiempo de espera para la llamada a la función C (como se describe en este hilo C++: How to implement a timeout for an arbitrary function call?), pero necesitaría pensar cuidadosamente en qué tipo de estado dejaría la base de datos, presumiblemente solo para lecturas de la base de datos, no insertos/actualizaciones.

+0

) He tenido un problema similar con OCCI y fue "resuelto" de esta manera - con temporizador. Pero el problema era más grande allí - entonces, cuando expira el temporizador, llamo 'exit (1); (horrible, lo sé, pero no se encontró ninguna otra solución, incluso un desarrollador de Oracle no pudo ayudar). De todos modos, esta es una mala solución, estoy buscando una más inteligente. Gracias de todos modos por la idea (Y) –

+0

Creo que esta es la manera general de manejar recursos externos sin bloquear. Esto es esencialmente cómo se maneja cualquier llamada de recurso de bloqueo si el sistema operativo no tiene esa funcionalidad integrada. Consulte la programación de socket. –

0

Si no le importa usar hilos, puede iniciar la consulta desde un nuevo hilo y hacer que el hilo principal realice un corto pthread_cond_timedwait para el nuevo hilo para establecer una variable de condición que hace la conexión. Entonces puede dejar que el hilo permanezca hasta que la llamada real de mysql expire. Solo asegúrate de que esté desacoplado para que sus recursos se liberen cuando finalmente se agote el tiempo de espera. Esta solución no es bonita, pero al menos debería funcionar.

+0

No puedo hacer esto para cada consulta, ya que esto ralentizará el trabajo de la aplicación, que se supone que procesa más de 1000 mensajes por segundo. Gracias de todos modos –

+0

Esto no debería ser un problema de rendimiento con 1000 hilos por segundo, pero podría rápidamente n de los recursos del kernel para crear tantos hilos si no salen rápidamente. :( –

Cuestiones relacionadas