2009-01-06 103 views

Respuesta

-4

No conozco una forma de hacerlo en mysql, pero como está familiarizado con set_time_limit() en php, ¿por qué no ejecutar la consulta SQL en un script php para limitar el tiempo?

+10

Estoy bastante seguro de que incluso si el script PHP sale después de que el tiempo de espera, MySQL mantendrá el procesamiento de la consulta que se le dio. – Rafa

+0

el tiempo de ejecución de la base de datos no afecta 'set_time_limit()' – JamesHalsall

+0

@JamesHalsall (Excepto en Windows, donde 'set_time_limit()' establece un límite de tiempo de reloj de pared en lugar de un límite de tiempo de ejecución) –

4

Puede encontrar la respuesta en este otro S.O. pregunta:

MySQL - can I limit the maximum time allowed for a query to run?

una tarea programada que se ejecuta cada segundo en el servidor de base de datos, conectar y hacer algo como esto:

  • SHOW PROCESSLIST
  • Encuentra todas las conexiones con un tiempo de consulta más grande que su tiempo máximo deseado
  • Ejecutar KILL [id de proceso] para cada uno de esos procesos
18

pensé que ha sido alrededor de un poco más de tiempo, pero de acuerdo con this,

MySQL 5.7.4 introduce la posibilidad de establecer límites de tiempo de ejecución del lado del servidor, en milisegundos, para la lectura de nivel superior -solo declaraciones SELECT.

SELECT 
MAX_EXECUTION_TIME = 1000 --in milliseconds 
* 
FROM table; 

Tenga en cuenta que esto sólo funciona para sólo lectura instrucciones SELECT.

Actualización: se añadió Esta variable en MySQL 5.7.4 y renombrado a max_execution_time en MySQL 5.7.8. (source)

+0

¿Será activo solo para esta consulta o todas las consultas siguientes que comparten la misma sesión (id del proceso)? – mgutt

+0

Solo se aplica a la consulta en la que se especifica. Si va a mi fuente citada, puede establecer un global o sesión max_execution_time. – Westy92

+0

Sí, lo leí, pero no hay ninguna explicación de lo que 'sesión 'significa porque, por ejemplo,' KILL' necesita explícitamente el modificador 'QUERY': https://dev.mysql.com/doc/refman/5.7/en/kill. html Y en esta respuesta 'session' se explicó como una otra palabra para' connection': http://stackoverflow.com/a/8800971/318765 – mgutt

7

Si está utilizando el mysql native driver (común a partir de PHP 5.3), y la extensión mysqli, se puede lograr esto con una consulta asincrónica:

<?php 

// Here's an example query that will take a long time to execute. 
$sql = " 
    select * 
    from information_schema.tables t1 
    join information_schema.tables t2 
    join information_schema.tables t3 
    join information_schema.tables t4 
    join information_schema.tables t5 
    join information_schema.tables t6 
    join information_schema.tables t7 
    join information_schema.tables t8 
"; 

$mysqli = mysqli_connect('localhost', 'root', ''); 
$mysqli->query($sql, MYSQLI_ASYNC | MYSQLI_USE_RESULT); 
$links = $errors = $reject = []; 
$links[] = $mysqli; 

// wait up to 1.5 seconds 
$seconds = 1; 
$microseconds = 500000; 

$timeStart = microtime(true); 

if (mysqli_poll($links, $errors, $reject, $seconds, $microseconds) > 0) { 
    echo "query finished executing. now we start fetching the data rows over the network...\n"; 
    $result = $mysqli->reap_async_query(); 
    if ($result) { 
     while ($row = $result->fetch_row()) { 
      // print_r($row); 
      if (microtime(true) - $timeStart > 1.5) { 
       // we exceeded our time limit in the middle of fetching our result set. 
       echo "timed out while fetching results\n"; 
       var_dump($mysqli->close()); 
       break; 
      } 
     } 
    } 
} else { 
    echo "timed out while waiting for query to execute\n"; 
    var_dump($mysqli->close()); 
} 

Las banderas que estoy dando a mysqli_query lograr cosas importantes. Le dice al controlador del cliente que habilite el modo asíncrono, mientras que nos obliga a usar un código más detallado, pero nos permite usar un tiempo de espera (¡y también emitir consultas concurrentes si lo desea!). La otra bandera le dice al cliente que no almacene en búfer todo el conjunto de resultados en la memoria.

De forma predeterminada, php configura sus bibliotecas de cliente mysql para recuperar todo el conjunto de resultados de su consulta en la memoria antes de permitir que su código php comience a acceder a las filas en el resultado. Esto puede llevar mucho tiempo para transferir un resultado grande. Lo deshabilitamos, de lo contrario corremos el riesgo de que se agote el tiempo de espera mientras se completa el almacenamiento en búfer.

Tenga en cuenta que hay dos lugares en los que necesitamos para comprobar por exceder un límite de tiempo:

  • La consulta real de ejecución
  • , mientras que ir a buscar los resultados (datos)

que puede lograr similares en el PDO y extensión mysql regular. No admiten consultas asincrónicas, por lo que no puede establecer un tiempo de espera en el tiempo de ejecución de la consulta. Sin embargo, admiten conjuntos de resultados sin búfer, por lo que al menos puede implementar un tiempo de espera en la obtención de los datos.

Para muchas consultas, mysql puede comenzar a transmitirle los resultados casi de inmediato, por lo que las consultas sin búfer por sí solas le permitirán implementar efectivamente los tiempos de espera en ciertas consultas. Por ejemplo, un

select * from tbl_with_1billion_rows 

puede empezar a transmitir filas de inmediato, pero,

select sum(foo) from tbl_with_1billion_rows 

necesita para procesar toda la tabla antes de que pueda comenzar a devolver la primera fila en su caso. Este último caso es donde el tiempo de espera en una consulta asincrónica lo salvará. También lo salvará de viejos bloqueos y otras cosas.

ps - No incluí ninguna lógica de tiempo de espera en la conexión en sí.

+0

Esto es increíble ..... No puedo esperar a probarlo ... genial para consultas de gráficos de datos, por ejemplo .... –

+0

esto no detendrá una consulta mysql que está en proceso en el servidor sql. una excelente solución para una pregunta diferente, sin embargo. – TheSatinKnight

+0

@TheSatinNight ¿estás seguro de eso? La llamada a 'query()' es asincrónica, por lo que regresa al instante. La siguiente llamada es 'poll()', que tiene un tiempo de espera. la encuesta solo producirá consultas que están listas para ser cosechadas ... entonces, ¿dónde está esta "consulta en proceso" de la que usted habla? – goat

0

pt_kill tiene una opción para tal. Pero es bajo demanda, no monitoreando continuamente. Hace lo que sugirió @Rafa. Sin embargo, vea --sentinel para obtener una idea de cómo acercarse con cron.

0

Por favor, vuelva a escribir la consulta como

select /*+ MAX_EXECUTION_TIME(1000) */ * from table

Cuestiones relacionadas