Ich benutze PDO, und der Benutzer sollte die Möglichkeit haben, die Anfrage zu stoppen, die er vorher ausgelöst hat.
Beispiel: Ich klicke jetzt auf "Bericht generieren", habe aber nach der Anfrage vergessen, ein weiteres Feld auszuwählen, das den Bericht unbrauchbar macht. Also muss ich die Anfrage abbrechen und eine neue machen.
Wie kann ich die laufende MySQL-Abfrage abbrechen?
%Vor%Ich weiß, dass ich den Kill-Befehl und den PID-Prozess verwenden kann, aber das sollte durch PDO laufen, und ich weiß nicht, was die PID ist.
Das Hauptproblem besteht darin, die PID zwischen Ihrer asynchronen Anfrage, die den Bericht generiert, und dem Skript, das sie stoppen sollte, zu teilen.
Sie können Ihre PID mit:
erhalten %Vor%Und Sie können etwas wie php-shared-memory verwenden, um eine gemeinsame Variable zwischen Ihren Skripten zu erstellen. Wenn Sie Composer nicht für Ihre Projektabhängigkeiten verwenden, verfügt diese Bibliothek über eine eigenständige Version (1.5.0, hier ).
Implementierungsbeispiel:
%Vor% Wie bereits erwähnt, können Sie sich bei Ihrem MySQL-Server anmelden, SHOW PROCESSLIST
ausgeben, die Nummer der abzustellenden Abfrage suchen und dann den Befehl KILL number
ausgeben.
Es scheint so, als ob Sie möchten, dass diese Funktion für Ihre Benutzer, die Berichte erstellen, selbstbedient ist, anstatt dass sie jemanden in Ihren Net-Ops anrufen und sie bitten, dies zu tun, oder ihnen beibringen, ein Verwaltungswerkzeug zu verwenden.
Ich habe so etwas schon einmal gemacht. Es besteht aus drei Teilen.
Zuerst müssen Sie veranlassen, dass ein Tag in die Art von Abfragen eingefügt wird, die Ihre Benutzer möglicherweise abbrechen möchten. Zum Beispiel, wenn Ihr Benutzer dies tut
%Vor%Sie müssen den Text der Abfrage so ändern, dass ein Tag beispielsweise in einen Kommentar eingebettet wird.
%Vor% Beachten Sie, dass dieses Tag zwei Elemente enthält: report:
und eine Benutzer-ID. Die Benutzer-ID muss etwas sein, das sich nicht auf die Verbindung bezieht, auf der die Abfrage ausgeführt wird. Diese Verbindung wird gebunden, wenn Sie versuchen, die darauf ausgeführte Abfrage aufzugeben. Das Tag beeinflusst die Ausführung der Abfrage überhaupt nicht. Es erscheint nur in der Prozesstabelle des Servers.
Zweitens: Ihr PDO-Code, der diese Abfragen ausführt, wird eine gute und benutzerfreundliche Ausnahmebehandlung benötigen, da die Abfragen, die unter Ihrem Code explodieren, zur Routine werden. Sie müssen damit experimentieren, um diese Abbruch-Abfrage-Funktion für Ihre Benutzer nützlich zu machen.
Drittens: Führen Sie diese Abfrage aus, wenn Sie die Berichtsabfrage für user2290084
beenden müssen %Vor%Es wird in der Prozessliste nach der Prozess-ID für eine Abfrage mit dem entsprechenden Tag gesucht. Dann stelle
aus %Vor%und Sie haben die Abfrage abgebrochen.
In PHP könnte es so aussehen:
%Vor%Beachten Sie, dass in diesem Code eine Schleife enthalten ist. Es ist möglich, dass mehr als eine Berichtsabfrage für diesen Benutzer oder keine ausgeführt wird.
Da Sie bereits eine Abfrage ausführen und eine zweite Transaktion durchführen, um sie abzubrechen, müssen Sie einige Informationen über die laufende Abfrage erhalten.
Show processlist
zeigt alle Abfragen an, sucht die richtige und gibt den Befehl kill
(in MySQL)
Sie werden einige Informationen brauchen, um dagegen zu passen. Die Infobox zeigt die Abfrage als getippt an. Sie können einen Kommentar mit einer Zufallszahl hinzufügen, die Sie in der Sitzung speichern. Ordnen Sie dann den zufälligen Wert der Sitzung den Zeilen aus dem Ergebnis von show processlist
zu, damit der Abfragecache immer noch verwendet werden kann und genau übereinstimmen muss, was Sie benötigen
Obwohl die Tatsache, dass Ihre Abfragen lang genug sind, um so etwas zu erfordern, vorschlägt, sollten Sie sich ansehen, warum die Abfragen das langsam sind.
Dies ist eine Lösung, die wir auf einem unserer Systeme verwenden. Es gibt zwei verschiedene Komponenten (die Benutzeroberfläche und den Berichtsprozessor), die die Datenbank für die Kommunikation verwenden.
Die Benutzeroberfläche sammelt die Berichtsparameter vom Benutzer und erstellt dann einen neuen Eintrag in der Berichtstabelle mit dem Status new
. Die Berichterstellung wird nicht automatisch gestartet.
Auf der Benutzeroberfläche werden alle Berichte mit ihrem aktuellen Status aufgelistet ( new
, waiting
, running
, killed
, completed
, failed
). Wenn der Kunde mit den Berichtsparametern zufrieden ist, die er auswählt, bildet er die Liste der Berichte und drückt die Schaltfläche "Bericht starten", die den Berichtsstatus von new
in waiting
ändert.
Ein Cron-Job, der jede Minute auf dem Server ausgeführt wird, wählt den ersten Bericht im Status waiting
aus, ändert seinen Status in running
und beginnt mit dem Sammeln der Daten aus der Datenbank. Nach Abschluss des Vorgangs wird der Status in completed
(oder failed
, falls etwas schief gelaufen ist) geändert und ein Kommentarfeld mit dem Ergebnis der Operation aktualisiert (die Fehlermeldung bei einem Fehler).
Der Kunde sieht den aktuellen Status aller Berichte in der Benutzeroberfläche. Wenn sie einen laufenden Bericht stoppen möchten, verwenden sie den "Kill" -Button und die Benutzeroberfläche ändert den Status des Berichts in der Datenbank in killed
.
Die Berichterstellung umfasst mehrere Phasen und viele Anfragen an die Datenbank. Zwischen diesen Phasen und sogar während dieser Phase, wenn eine Phase viele Schritte umfasst, überprüft das Skript den Status des Berichts, den es verarbeitet. Solange der Status running
lautet, werden die Daten weiterhin gesammelt und der Bericht erstellt. Wenn der Status in killed
geändert wurde, weiß er, dass der Benutzer seine Meinung geändert hat. Es stoppt die Verarbeitung, ändert den Status des Berichts in failed
, aktualisiert den Kommentar (auf "vom Benutzer getötet"), bereinigt die Dinge und beendet sie.
Dies ist nur eine Skizze. Es gibt mehr Prozesestatus und auch Code, der zwei Instanzen des Cron-Jobs für die Verarbeitung des gleichen Berichts behält, aber dieses Modell funktioniert für uns mehr als vier Jahre ohne nennenswerte Probleme.
In Bezug auf die Laufzeit benötigen kleine Berichte mehrere Sekunden, aber größere Berichte dauern manchmal 2-3 Stunden. Während 5 bis 10 Sekunden Berichte können abgeschlossen und danach gelöscht werden, früh töten einen Bericht, der nicht benötigt wird und würde sonst ein paar Stunden bis zum Abschluss rechtfertigen die Implementierung eines komplexen Mechanismus.