2009-01-06 8 views

Antwort

-4

Ich bin mir nicht bewusst, eine Möglichkeit, dies in mysql, aber da Sie mit set_time_limit() in PHP vertraut sind, warum nicht die SQL-Abfrage in einem PHP-Skript ausführen, um die Zeit zu begrenzen?

+10

ich mir ziemlich sicher bin, dass auch wenn das PHP-Skript, nachdem es beendet mal aus, MySQL halten die Abfrage der Verarbeitung, die gegeben wurde. – Rafa

+0

Datenbankausführungszeit wirkt sich nicht aus 'set_time_limit()' – JamesHalsall

+0

@JamesHalsall (Außer in Windows, wo 'set_time_limit()' ein Wanduhrzeitlimit anstelle eines Ausführungszeitlimits setzt.) –

4

Sie können die Antwort auf diese anderen S.O finden. Frage:

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

ein Cron-Job, der jede Sekunde auf dem Datenbank-Server ausgeführt wird, verbinden und so etwas wie dies zu tun:

  • SHOW PROCESS
  • Suche alle Verbindungen mit einer Abfragezeit größer als die maximal gewünschte Zeit
  • Führen Sie KILL [Prozess-ID] für jeden dieser Prozesse aus
18

Ich dachte, es hat schon ein wenig länger, aber nach this,

MySQL 5.7.4 führt die Möglichkeit eines serverseitige Ausführung Fristen gesetzt werden, in Millisekunden angegeben, für Top-Level-Lese -nur SELECT-Anweisungen.

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

Beachten Sie, dass dies nur funktioniert, für schreibgeschützte Anweisungen SELECT.

Update: Diese Variable wurde in MySQL hinzugefügt 5.7.4 und max_execution_time in MySQL 5.7.8 umbenannt. (source)

+0

Wird es sein Nur für diese Abfrage aktiv oder für alle folgenden Abfragen, die dieselbe Sitzung teilen (Prozess-ID)? – mgutt

+0

Es gilt nur für die Abfrage, in der es angegeben ist. Wenn Sie zu meiner zitierten Quelle gehen, können Sie eine globale oder Sitzung max_execution_time festlegen. – Westy92

+0

Ja, ich lese das, aber es gibt keine Erklärung, was "Sitzung" bedeutet, weil zum Beispiel 'KILL' explizit den Modifikator' QUERY' benötigt: https://dev.mysql.com/doc/refman/5.7/en/kill. html Und in dieser Antwort wurde "Sitzung" als ein anderes Wort für 'Verbindung' erklärt: http://StackOverflow.com/a/8800971/318765 – mgutt

7

Wenn Sie mit dem mysql native driver (common seit PHP 5.3) und die mysqli Erweiterung, können Sie dies mit einer asynchronen Abfrage auszuführen:

<?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()); 
} 

Die Flaggen ich geben werde, um mysqli_query wichtige Dinge erreichen. Es weist den Clienttreiber an, den asynchronen Modus zu aktivieren, während wir gezwungen sind, ausführlicheren Code zu verwenden, aber wir können ein Zeitlimit verwenden (und bei Bedarf auch gleichzeitige Abfragen ausführen). Das andere Flag weist den Client an, die gesamte Ergebnismenge nicht im Speicher zwischenzuspeichern.

Standardmäßig konfiguriert php seine mysql-Client-Bibliotheken so, dass der gesamte Ergebnissatz Ihrer Abfrage in den Speicher geladen wird, bevor Ihr PHP-Code auf Zeilen im Ergebnis zugreift. Dies kann lange dauern, um ein großes Ergebnis zu übertragen. Wir deaktivieren es, sonst riskieren wir, dass wir eine Zeitüberschreitung haben, während wir auf das Ende der Pufferung warten.

Beachten Sie, dass zwei Orte gibt es, wo wir für die Überschreitung einer Frist überprüfen müssen:

  • Die tatsächliche Ausführung der Abfrage
  • während die Ergebnisse (Daten) Abrufen

Sie können ähnlich erreichen in der PDO und regulären mysql-Erweiterung. Sie unterstützen keine asynchronen Abfragen. Sie können daher kein Zeitlimit für die Ausführungszeit der Abfrage festlegen. Sie unterstützen jedoch ungepufferte Ergebnismengen, sodass Sie beim Abrufen der Daten zumindest eine Zeitüberschreitung implementieren können.

Bei vielen Abfragen kann mysql fast sofort mit dem Streamen der Ergebnisse beginnen, und so können Sie allein durch ungepufferte Abfragen Timeouts bei bestimmten Abfragen effektiv implementieren. Zum Beispiel kann ein

select * from tbl_with_1billion_rows 

können Zeilen sofort beginnen Streaming, aber

select sum(foo) from tbl_with_1billion_rows 

muss die gesamte Tabelle verarbeiten, bevor es die erste Zeile der Rückkehr in Sie beginnen können. In diesem letzteren Fall wird das Zeitlimit für eine asynchrone Abfrage Sie speichern. Es wird dich auch vor einfachen alten Deadlocks und anderem Zeug bewahren.

ps - Ich habe keine Timeout-Logik auf der Verbindung selbst enthalten.

+0

Das ist unglaublich ..... Ich kann es kaum erwarten, es zu versuchen ..... toll für Graph Datenabfragen zum Beispiel .... –

+0

Dies wird nicht stoppen eine MySQL-Abfrage, die auf dem SQL-Server in Bearbeitung ist. eine ausgezeichnete Lösung für eine andere Frage. – TheSatinKnight

+0

@TheSatinNight bist du dir sicher? Der Aufruf von 'query()' ist asynchron, so dass er sofort zurückkehrt. Der nächste Aufruf ist 'poll()', mit einem Timeout. Umfrage erzeugt nur Abfragen, die bereit sind, geerntet zu werden ... also wo ist diese "Abfrage in Bearbeitung", von der Sie sprechen? – goat

0

pt_kill hat eine Option für solche. Aber es ist auf Abruf, nicht ständig zu überwachen. Es macht was @Rafa vorgeschlagen hat. Jedoch sehen Sie --sentinel für einen Hinweis, wie man mit cron nah kommt.

0

Schreiben Sie bitte Ihre Abfrage wie

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