mysqli Abfrage parallel
mixmastertobsi
- datenbank
0 dedlfix0 TS- datenbank
- php
Hallo,
ich habe ein Problem mit MYSQLI.
Ich habe ein Skript, welches ich starte und die DB-Abfrage dauert ca. 10 Minuten, weil das Skript ca. 100.000 Artikel exportieren muss. Wenn ich nun in dieser Zeit ein anderes PHP-Skript starte (mit eine SQL Abfrage), wird dieses erst ausgeführt, wenn das erste Skript beendet wird. Wo muss ich hier etwas umstellen, dass von einem User mehrere Anfragen parallel gestartet werden können/dürfen?
Tach!
Wenn ich nun in dieser Zeit ein anderes PHP-Skript starte (mit eine SQL Abfrage), wird dieses erst ausgeführt, wenn das erste Skript beendet wird. Wo muss ich hier etwas umstellen, dass von einem User mehrere Anfragen parallel gestartet werden können/dürfen?
Zunächst erstmal solltest du ermitteln, an welcher Stelle es nun konkret bremst. Wird wirklich der gesamte PHP-Prozess auf Halde gelegt, oder wartet PHP erst beim Verbindungsaufbau zur Datenbank oder zu einer anderen Gelegenheit? Kontrollausgaben können den Fortschritt aufzeigen. Bedenke, dass Webserver und Browser die Ausgabe/Anzeige puffern können. Zeitstempel sind sinnvoll, um die genauen Verhältnisse du dokumentieren.
Ansonsten kann ich nur sagen, dass es eine ganze Menge Möglicheiten der Konstellation und Konfiguration gibt, wie man Webserver, gegebenenfalls zuzüglich FCGI-Wrapper, PHP und DBMS zusammenbringen kann. Da gibt es eine Menge Stellen, an denen da die Weiterverarbeitung aufgehalten werden kann. Auch der Browser kann den Request zurückhalten, bis der erste fertig ist. In einem anderen Browser den Request zu probieren wäre ein erster Test.
dedlfix.
Hallo,
also wenn ich in einem anderen Browser das gleiche Skript starte, klappt es problemlos.
Wenn ich bei dem Skript die SQL-Abfrage entferne und zum Beispiel nur echo "OK"; ausgebe, wird das Skript auch gleich geladen. Es muss also an MYSQL liegen in Verbindung mit dem selben Server.
Noch eine Idee?
Tach!
also wenn ich in einem anderen Browser das gleiche Skript starte, klappt es problemlos.
Und wie passt das dann zu der Vermutung, dass das Zusammenspiel mit MySQL das Problem darstellt, wenn es parallel im anderen Browser problemlos durchläuft?
Wenn ich bei dem Skript die SQL-Abfrage entferne und zum Beispiel nur echo "OK"; ausgebe, wird das Skript auch gleich geladen. Es muss also an MYSQL liegen in Verbindung mit dem selben Server.
Vielleicht ein Session-Problem? Eine Session-Datei wird zwischen Öffnen und explizitem Schließen oder implizitem Schließen am Script-Ende gesperrt und ein weiterer PHP-Prozess mit derselben Session-ID wartet brav auf dessen Freigabe.
dedlfix.
Danke, das ist das Problem. Hier gibt es vermutlich keine Lösung - oder?
Tach!
Danke, das ist das Problem. Hier gibt es vermutlich keine Lösung - oder?
Die Session zu Fuß schließen, wenn du sie nicht mehr brauchst. Gegebenenfalls öffnest du sie eben nach dem länger dauernden Teil erneut.
dedlfix.
Bei meinem Skript wird die Session Global geöffnet. Macht das überhaupt Sinn, oder sollte man diese öffnen, nur wenn man diese auch braucht. Weil sonst müsste ich die Session permanent öffnen/schließen - die Frage ist, ob das performanter ist?!?
Tach!
Bei meinem Skript wird die Session Global geöffnet. Macht das überhaupt Sinn, oder sollte man diese öffnen, nur wenn man diese auch braucht. Weil sonst müsste ich die Session permanent öffnen/schließen - die Frage ist, ob das performanter ist?!?
Die Frage nach der Performance ist zweitrangig. Wichtig ist, dass es überhaupt läuft. Wenn die Laufzeit dann akzeptabel ist, muss man sich meist keine weiteren Gedanken zur Performance machen. Es sei denn, du weißt genau, dass du da einen Flaschenhals eingebaut hast, beispielsweise mit einem eigenen Session-Handling oder übermäßig vielen Daten in der Session-Datei.
Und warum muss die Session permanent geöffnet und geschlossen werden? Man kann die Daten auch einmal lesen und am Ende wieder schreiben. Während der Script-Laufzeit liegen sie dann in einem normalen Array. Zu beachten sind dann aber Nebenläufigkeitseffekte. Nicht umsonst blockiert PHP ja das Script, wenn es die Session-Datei wegen bereits anderer Verwendung nicht öffnen kann.
dedlfix.
Bei meinem Skript wird die Session Global geöffnet. Macht das überhaupt Sinn, oder sollte man diese öffnen, nur wenn man diese auch braucht.
1.) Du machst ja auch die Milch nicht auf, nur weil die gekauft wurde.
2.) Wenn es Dir nur darum geht, die Session zu lesen und z.B. eine Zugangsberechtigung einmalig zu prüfen, dann kannst Du die Session danach auch wieder zumachen. Speichere in dem Fall relevante (oder halt alle) Daten in einer Kopie des Session-Variable.
Weil sonst müsste ich die Session permanent öffnen/schließen
Alles, aber das bitte nicht. "Normale" PHP-Skripte sind in ein paar hundertstel Sekunden oder schneller abgearbeitet und parallele identische Sessions eigentlich die Ausnahme.
Hallo und guten Morgen,
Bei meinem Skript wird die Session Global geöffnet. Macht das überhaupt Sinn, oder sollte man diese öffnen, nur wenn man diese auch braucht.
Die spannende Frage ist dann: Was passiert mit den Daten im Session-Array, wenn man die Session erneut öffnet. Probier es aus!
2.) Wenn es Dir nur darum geht, die Session zu lesen und z.B. eine Zugangsberechtigung einmalig zu prüfen, dann kannst Du die Session danach auch wieder zumachen. Speichere in dem Fall relevante (oder halt alle) Daten in einer Kopie des Session-Variable.
Die Umsetzung hängt vom vorgesehen Konzept ab.
und den diveresen Spielarten.
Grüße
TS
Hallo und guten Morgen,
Bei meinem Skript wird die Session Global geöffnet. Macht das überhaupt Sinn, oder sollte man diese öffnen, nur wenn man diese auch braucht.
Die spannende Frage ist dann: Was passiert mit den Daten im Session-Array, wenn man die Session erneut öffnet. Probier es aus!
<?php
session_start();
$_SESSION['farbe'] = 'grün';
$_SESSION['tier'] = 'Spinne';
$_SESSION['zeit'] = time();
$mySession = $_SESSION;
session_write_close();
session_start();
echo '$_SESSION:', "\n";
print_r($_SESSION);
echo 'Kopie:', "\n";
print_r($_SESSION);
Ergebnis wie erwartet:
~$ php /tmp/test3.php
$_SESSION:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477655968
)
Kopie:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477655968
)
Kommt wohl darauf an, wie man die Session startet. Mit session_destroy()
statt session_write_close()
sieht das Ergebnis zwingend anders aus:
$ php /tmp/test3.php
$_SESSION:
Array
(
)
Kopie:
Array
(
)
Hallo und guten Tag J.,
Die spannende Frage ist dann: Was passiert mit den Daten im Session-Array, wenn man die Session erneut öffnet. Probier es aus!
<?php
session_start();
$_SESSION['farbe'] = 'grün';
$_SESSION['tier'] = 'Spinne';
$_SESSION['zeit'] = time();
$mySession = $_SESSION;
session_write_close();
$_SESSION['neu'] = 'hast Du vergessen';
$_SESSION['neu'][2] = 'und noch ein Gedicht';
echo '$_SESSION:', "\n";
print_r($_SESSION);
session_start();
echo '$_SESSION:', "\n";
print_r($_SESSION);
echo 'Kopie:', "\n";
print_r($_SESSION);
Ergebnis wie erwartet:
~$ php /tmp/test3.php $_SESSION: Array ( [farbe] => grün [tier] => Spinne [zeit] => 1477655968 ) Kopie: Array ( [farbe] => grün [tier] => Spinne [zeit] => 1477655968 )
Kommt wohl darauf an, wie man die Session startet. Mit
session_destroy()
stattsession_write_close()
sieht das Ergebnis zwingend anders aus:$ php /tmp/test3.php $_SESSION: Array ( ) Kopie: Array ( )
Dein Versuch war unvollständig. Das wichtigste hast Du vergessen!
und nun?
Grüße
TS
Die spannende Frage ist dann: Was passiert mit den Daten im Session-Array, wenn man die Session erneut öffnet. Probier es aus!
Dein Versuch war unvollständig. Das wichtigste hast Du vergessen!
- Öffen
- Array beschreiben
- Schließen
- Array weiter beschreiben
- erneut öffnen
und nun?
<?php
ob_start();
session_start();
$_SESSION['farbe'] = 'grün';
$_SESSION['tier'] = 'Spinne';
$_SESSION['zeit'] = time();
$mySession=$_SESSION;
#session_destroy();
session_write_close();
$mySession['ha'] = 'foo';
echo 'Kopie nach write_close:', "\n";
print_r($mySession);
session_start();
echo '$_SESSION nach Reopen:', "\n";
print_r($_SESSION);
echo 'Kopie nah Reopen:', "\n";
print_r($mySession);
Ergebnis:
Kopie nach write_close:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477656929
[ha] => foo
)
$_SESSION nach Reopen:
Array
(
)
Kopie nah Reopen:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477656929
[ha] => foo
)
Alles wie erwartet.
wenn Du auch in der Konsole die gleiche Session wieder haben willst:
<?php
ob_start();
session_start();
$_SESSION['farbe'] = 'grün';
$_SESSION['tier'] = 'Spinne';
$_SESSION['zeit'] = time();
$mySession=$_SESSION;
$sessId=session_id();
#session_destroy();
session_write_close();
$mySession['ha'] = 'foo';
echo 'Kopie nach write_close:', "\n";
print_r($mySession);
session_start($sessId);
echo '$_SESSION nach Reopen:', "\n";
print_r($_SESSION);
echo 'Kopie nah Reopen:', "\n";
print_r($mySession);
Ergebnis:
php /tmp/test3.php
Kopie nach write_close:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477657342
[ha] => foo
)
$_SESSION nach Reopen:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477657342
)
Kopie nah Reopen:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477657342
[ha] => foo
)
Tach!
und nun?
Darüber nachdenken, warum man besser nicht direkt in globalen Dingen rumfummelt, sondern sich per Dependency Injection das Zeug geben lässt, das verwendet werden soll. Dann kann der Session-Service sich um alles kümmern und der Rest der Anwendung muss sich keine Sorgen machen.
dedlfix.
Hallo und guten Morgen,
Bei meinem Skript wird die Session Global geöffnet. Macht das überhaupt Sinn, oder sollte man diese öffnen, nur wenn man diese auch braucht.
Die spannende Frage ist dann: Was passiert mit den Daten im Session-Array, wenn man die Session erneut öffnet. Probier es aus!
<?php
ob_start();
session_start();
$_SESSION['farbe'] = 'grün';
$_SESSION['tier'] = 'Spinne';
$_SESSION['zeit'] = time();
$mySession=$_SESSION;
session_write_close();
echo 'Kopie nach write_close:', "\n";
print_r($mySession);
session_start();
echo '$_SESSION:', "\n";
print_r($_SESSION);
echo 'Kopie:', "\n";
print_r($mySession);
Ergebnis wie erwartet:
Kopie nach write_close:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477656741
)
$_SESSION:
Array
(
)
Kopie:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477656741
)
Kommt wohl darauf an, wie man die Session startet. Mit session_destroy()
statt session_write_close()
sieht das Ergebnis zwingend anders aus:
$ php /tmp/test3.php
Kopie nach write_close:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477656618
)
$_SESSION:
Array
(
)
Kopie:
Array
(
[farbe] => grün
[tier] => Spinne
[zeit] => 1477656741
)
Hallo und guten Morgen,
Danke, das ist das Problem. Hier gibt es vermutlich keine Lösung - oder?
Doch.
\1. Verzichte auf die Session oder starte eine weitere Session. Das geht z.B., indem Du die Skripte aus verschiedenen Pfaden heraus startest und den Sessioncookie nicht ab Domain-Root setzt, sondern eben nur für das jeweilige Verzeichnis. Andere Konstrukte sind auch noch möglich, aber das ist mMn der einfachste Weg, weil man dasselbe Skript verwenden kann (Kopien davon).
siehe http://php.net/manual/en/session.configuration.php#ini.session.cookie-path
\2. Wenn Du Zugriff auf die Exec-Funktion von PHP hast und PHP-CLI installiert ist, kannst Du den eigentlichen Datenbankprozess in den Hintergrund stellen. Merk Dir aber in einer Kontrolldatei die PID. Dann kannst Du mit dem Hauptskript gleich alle DB-Zugriffe auf einmal starten und das Fenster auch schließen. Mit einem anderen Skript kannst Du dann später nachschauen, ob die PID aus der Kontrolldatei noch lebt oder beendet ist.
Grüße
TS
Hallo und guten Tag,
\2. Wenn Du Zugriff auf die Exec-Funktion von PHP hast und PHP-CLI installiert ist, kannst Du den eigentlichen Datenbankprozess in den Hintergrund stellen. Merk Dir aber in einer Kontrolldatei die PID. Dann kannst Du mit dem Hauptskript gleich alle DB-Zugriffe auf einmal starten und das Fenster auch schließen. Mit einem anderen Skript kannst Du dann später nachschauen, ob die PID aus der Kontrolldatei noch lebt oder beendet ist.
$pid = exec("/pfad/zum/php db_script.php > /dev/null & echo $!");
Das db_script.php darf dann freilich keine Session starten, sonst hast Du das Problem wieder.
Grüße
TS
Hallo und guten Tag,
\1. Verzichte auf die Session oder starte eine weitere Session. Das geht z.B., indem Du die Skripte aus verschiedenen Pfaden heraus startest und den Sessioncookie nicht ab Domain-Root setzt, sondern eben nur für das jeweilige Verzeichnis. Andere Konstrukte sind auch noch möglich, aber das ist mMn der einfachste Weg, weil man dasselbe Skript verwenden kann (Kopien davon).
siehe http://php.net/manual/en/session.configuration.php#ini.session.cookie-path
Hier noch das kleine Testskriptlein für den Lösungsweg 1:
<?php ### session_start.php ### utf-8 ### äöüÄÖÜ
header('Content-Type: text/plain; charset=utf-8');
session_set_cookie_params (0, dirname($_SERVER['SCRIPT_NAME']), $_SERVER['HTTP_HOST']);
session_start();
print_r($_SESSION);
$_SESSION['user'] = 2;
$_SESSION['data']['time'] = time();
?>
jeweils untergebracht in einem anderen Pfad stören sich die Sessions dann nicht, vorausgesetzt, sie werden auch in diesem Pfad gestaret und nicht in einen anderen (gemeinsamen) eingebunden (include()).
Grüße
TS
Lösungsweg 1:
Wenn man "Lösungsweg 1" mit "beste Lösung" assoziiert, dann wäre bei der gegebenen Problemstellung das von Dir und mir vorgeschlagene "Abhängen" des Backups vom PHP-Skript der "Lösungsweg 1".
Lösungsweg 1:
Wenn man "Lösungsweg 1" mit "beste Lösung" assoziiert, dann wäre bei der gegebenen Problemstellung das von Dir und mir vorgeschlagene "Abhängen" des Backups vom PHP-Skript der "Lösungsweg 1".
"Mehrere Session" löst nur eines der vielen, durch die lange Dauer bedingten Probleme.
Danke, das ist das Problem. Hier gibt es vermutlich keine Lösung - oder?
Doch, gibt es. Die Sache erscheint mir sehr speziell, dass Du wohl das OS kennst und nutzen kannst. Hier mal für Linux/Unix/Mac:
Du startest den Export im Hintergrund und trennst ihn vollständig vom PHP-Skript:
$res = `echo "/usr/bin/php /pfad/zum/export-skript.php" | batch`;
#oder (schlechter)
$res = `echo "/usr/bin/php /pfad/zum/export-skript.php" | at now`;
batch
und at
setzen voraus, dass der Dienst atd
installiert ist und läuft. Das ist nicht mehr überall der Fall. Installiere das Paket 'at' wenn der Dienst fehlt, sich batch
oder at
also nicht in einem Terminal aufrufen lässt.
export-skript.php kann auch etwas ganz anderes sein, z.B. ein Shellskript. Es sollte wohl eine Datei bereitstellen, die das Ende bzw. den Erfolg des Prozesses markiert und durch ein weiteres PHP-Skript geprüft und gelöscht wird. Das kann z.B. via einer Ajax-Abfrage regelmäßig geschehen.
mktemp / tempnam könnte hier Wunder wirken :-)
Alternativ kann und sollte das Export-Skript ein Mail mit einem Download-Link für die Export-Datei senden. Grund: Eine Wartezeit von 10 Minuten halte ich für unvertretbar, denn in der Zeit kann clientseitig zu viel passieren
Hallo und guten Morgen,
wie sieht denn das Skript (verkürzt) aus?
HTML-Gesumse und CSS kannst Du auch weglassen.
Grüße
TS