Ich möchte eine maximale Ausführungszeit für SQL-Abfragen wie set_time_limit() in PHP setzen. Wie kann ich ?Wie setze ich eine maximale Ausführungszeit für eine MySQL-Abfrage?
Antwort
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?
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
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)
Wird es sein Nur für diese Abfrage aktiv oder für alle folgenden Abfragen, die dieselbe Sitzung teilen (Prozess-ID)? – mgutt
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
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
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.
Das ist unglaublich ..... Ich kann es kaum erwarten, es zu versuchen ..... toll für Graph Datenabfragen zum Beispiel .... –
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
@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
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.
Schreiben Sie bitte Ihre Abfrage wie
select /*+ MAX_EXECUTION_TIME(1000) */ * from table
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
Datenbankausführungszeit wirkt sich nicht aus 'set_time_limit()' – JamesHalsall
@JamesHalsall (Außer in Windows, wo 'set_time_limit()' ein Wanduhrzeitlimit anstelle eines Ausführungszeitlimits setzt.) –