j4nk3y: mysqli::query(): Couldn't fetch mysqli

Einen wunderschönen guten Abend zusammen,

Ich habe mal wieder ein problemchen, was mich nun schon den ganzen Abend durch die Suchergebnisse von google scheucht.

Ich habe ein php-file in dem, wenn ich es aufrufe eine Schleife, mit von mir vorgegebenen Schleifen-durchgängen, durchläuft.

Bis etwa 580 wiederholungen ist alles tutti und funktioniert so wie es soll. Und dann gibt mir mein mysqli Object durch

$error = $db->connect_error;

folgenden fehler aus:

"Ein Socketvorgang konnte nicht ausgeführt werden, da dem System Pufferspeicher fehlte oder eine Warteschlange voll war."

Zuerst dachte ich, dass ich an irgendeiner Stelle die Datenbankverbindung innerhalb der schleife nicht richtig schließe. Aber puste-kuchen, hab "sauber" gearbeitet.

Dann bleibt ja nur der Pufferspeicher über. Oder? Da stellt sich mir nur die Frage wie ich dieses problem lösen kann?

Danke schonmal für eure Hilfe!

Gruß

Jo

  1. Hallo

    Ich habe ein php-file in dem, wenn ich es aufrufe eine Schleife, mit von mir vorgegebenen Schleifen-durchgängen, durchläuft.

    Bis etwa 580 wiederholungen ist alles tutti und funktioniert so wie es soll. Und dann gibt mir mein mysqli Object … folgenden fehler aus:

    "Ein Socketvorgang konnte nicht ausgeführt werden, da dem System Pufferspeicher fehlte oder eine Warteschlange voll war."

    Du fragst in einer Schleife (mindestens) mehrere hundert Male eine Datenbank ab? Vermutlich handelt es sich doch um gleichartige Abfragen. Liegt eventuell schon hier der Hase im Pfeffer?

    Tschö, Auge

    --
    Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
    Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview
  2. Moin!

    Bis etwa 580 wiederholungen ist alles tutti und funktioniert so wie es soll. Zuerst dachte ich, dass ich an irgendeiner Stelle die Datenbankverbindung innerhalb der schleife nicht richtig schließe. Aber puste-kuchen, hab "sauber" gearbeitet.

    Soll heißen, Du baust in einem PHP-Skript 580 x mal die Datenbankverbindung auf und wieder ab. Und wunderst Dich, dass dabei ein Problem entsteht. Das Problem ist entweder sehr akademisch oder Du hast ein heftiges Problem mit dem Konzept.** Erstens** die hohe Anzahl der Abfragen (vermutlich nutzt Du keine Joins) und erst recht die der immer neuen Verbindungen. Die kann man nämlich mehrfach nutzen. Und wenn Du vorher nicht weisst, ab wann Du die nicht mehr brauchst: Beim Skriptende kommt der Besenmann (bei PHP als CGI). Spätestens nach Abbau der HTTP-Verbindung auch beim PHP als Apache-Modul-

    Ich habe gerade eben mit php 7.0.3 (PHP 7.0.3-9+deb.sury.org~trusty+3) beides getestet:

    <?php
        $i=0;
        while (0) {
            $mysqli = new mysqli();
            if ($mysqli->connect_error) {
                die('Connect Error (' . $mysqli->connect_errno . ') '
                        . $mysqli->connect_error);
            }
            if (mysqli_connect_error()) {
                die('Connect Error (' . mysqli_connect_errno() . ') '
                        . mysqli_connect_error());
            }
            echo ++$i . ' : Success... ' . $mysqli->host_info . "\n";
            $mysqli->close();
        }
    ?>
    

    [x] geht, bei ca. 50.000 manuell abgebrochen. Verbindung ging an localhost - also über socket, nicht port.

    Zweiter Test:

    <?php
    $i=0;
    while (1) {
        $link = mysqli_connect();
        if (!$link) {
            die('Connect Error (' . mysqli_connect_errno() . ') '
                    . mysqli_connect_error());
        }
    
        echo ++$i . ' : Success... ' . mysqli_get_host_info($link) . "\n";
        mysqli_close($link);
    }
    

    Ergebnis wie oben. Manuell abgebrochen.

    In allen beiden Fällen ist aber die Serverlast nicht zu verachten. Ein Massenhoster wird Dir Limits setzen.

    Dritter und vierter Test nicht zum localhost, sondern zur IP des Hosts (Aber NICHT: 127.0.0.1):

    Abbruch spätestens bei knapp 30.000 (beide!), sehr viel früher wenn ich die Skripte direkt nacheinander neu starte. Ich vermute mal, die Ports werden nicht schnell genug frei gegeben.- Auch hier gilt, dass Dir womöglich kleinere Limits gesetzt wurden.

    Jörg Reinholz

  3. Guten Morgen zusammen,

    Soll heißen, Du baust in einem PHP-Skript 580 x mal die Datenbankverbindung auf und wieder ab. Und wunderst Dich, dass dabei ein Problem entsteht.

    Ja und Ja. Kurz warum ich das so gestaltet habe. Das grundlegende Problem was ich sehe, wenn ich dieses Script ausführe, ist das Nutzer nicht auf die Datenbank zugreifen können oder Fehler bei deren querys entstehen. Durch die Transaction die ich starte und dann wieder beende könnten Nutzer "zwischendurch" ihre anfragen durchführen. Und ich wundere mich, weil ich als "fortgeschrittener laie" nicht verstehe warum den computern heutzutage noch grenzen gesetzt werden. (Inform von maximal 30.000 Datenbankverbindungen und wie ich nach mehreren Tests festgestellt habe nach rund 1.100.000 ausgeführten querys )

    In allen beiden Fällen ist aber die Serverlast nicht zu verachten. [Ein Massenhoster wird Dir Limits setzen]

    Das mit der Serverlast ist logisch aber wie erwähnt hätte ich nicht gedacht, dass die Limits so, in meinen Augen, "niedrig" liegen. Gut zu wissen, dass die Limits dann auch noch schärfer sein können. Danke.

    Du fragst in einer Schleife (mindestens) mehrere hundert Male eine Datenbank ab? Vermutlich handelt es sich doch um gleichartige Abfragen.

    Um genau zu sein wird in der Schleife, wenn sie 580 mal durchläuft, rund 1.100.000 Datenbankeinträge getätigt. Wie gesagt scheint, dass auch die maximale query anzahl zu sein unabhängig von der Anzahl an Datenbankverbindungen.

    Wie dem auch sei, weiß ich das jetzt und kann dementsprechend meinen code anpassen.

    Gruß

    Jo

    1. Moin!

      Und ich wundere mich, weil ich als "fortgeschrittener laie" nicht verstehe warum den computern heutzutage noch grenzen gesetzt werden.

      Weil die Technik eben Grenzen setzt. Überschallgeschwindigkeit auf Rädern geht nur mit sehr speziellen Material und auf sehr speziellen Strecken. Da nützt Dir der 1000-PS-Bolide auch auf deutschen Autobahnen nichts. MySQL ist für den Mehrbenutzerbetrieb vorgesehen, und deshalb steht auch der Bekloppte mit dem 1000-PS-Boliden am Montag morgen vor Frankfurt im Stau und muss sich an Regeln und Limits halten.

      (Inform von maximal 30.000 Datenbankverbindungen)

      Der Grund ist einfach. MySQL lauscht zwar (wenn nicht verbogen) auf Port 3306 aber jeder Client braucht für die Kommunikation auch einen Port. Zudem werden diese vom OS angefordert und vom OS verwaltet, also vergeben und wieder entzogen. Und deren Anzahl ist eben auf 2^16=65536 begrenzt und das OS gibt davon nur die Hälfte (2^15) dynamisch für die Benutzer frei. Das ist ein BASTA! Du kannst Dir aber gern selbst ein OS mit einem völlig eigenen Netzwerk schreiben.

      Durch die Transaction die ich starte und dann wieder beende und wie ich nach mehreren Tests festgestellt habe nach rund 1.100.000 ausgeführten querys )

      Da haben wir es gleich nochmal: Du verlangst zu viel. Die Transaktionen erfordern nämlich auch Speicher und Rechenleistung. Die Normalkonfiguration ist so, dass MySQL auf ganz normalen Rechnern mit ganz normaler Hardware auch bei einer beachtlichen Anzahl von Benutzern noch sehr gut funktioniert, also in vertretbarer Zeit Antworten liefert.

      Wenn es Dein eigener Server ist und wenn Du diesen für einen speziellen Anwendungszweck vorgesehen und mit der erforderlichen Hardware ausgerüstet, für Kühlung gesorgt hast und eine genügend hohe Stromrechnung budgetiert hast, dann kannst Du gerne im Handbuch Deiner Version nachlesen, wie Du die Limits selbst setzen kannst.

      Und da kommen wir zum nächsten Punkt:

      Warum machst Du sowas unter PHP? Für sowas gibt es zur Not den Standard-MySQL Client, dem man per Pipe einen Datenstrom reinschiebt echo datenstrom | mysql […] oder aber eine Datei lesen lasst mysql […] < datei. Und wenn Du mit den Netzwerk-Limits nicht leben kannst, dann schieb die Daten als Datei auf den Server und kippe diese dann über eine Socketverbindung, also via localhost in den Server.

      Aber auch dann wirst Du darauf achten müssen, dass Transaktionen Speicher brauchen, also begrenzt sind, also dass das System auf Deine sehr speziellen Aufgaben vorbereitet ist.

      Jörg Reinholz

      1. Morgen,

        (Inform von maximal 30.000 Datenbankverbindungen)

        Und deren Anzahl ist eben auf 2^16=65536 begrenzt und das OS gibt davon nur die Hälfte (2^15) dynamisch für die Benutzer frei. Das ist ein BASTA!

        Na wenn man sowas weiß, dann kommt man ja garnicht zur Frage was da schief läuft, sondern beachtet das schon in der überlegung, wie kann ich was umsetzen. Nur wusste ich das nicht, daher wunderte ich mich.

        Durch die Transaction die ich starte und dann wieder beende und wie ich nach mehreren Tests festgestellt habe nach rund 1.100.000 ausgeführten querys )

        Da haben wir es gleich nochmal: Du verlangst zu viel. Die Transaktionen erfordern nämlich auch Speicher und Rechenleistung. Die Normalkonfiguration ist so, dass MySQL auf ganz normalen Rechnern mit ganz normaler Hardware auch bei einer beachtlichen Anzahl von Benutzern noch sehr gut funktioniert, also in vertretbarer Zeit Antworten liefert.

        Soweit, so klar.

        Warum machst Du sowas unter PHP? Für sowas gibt es zur Not den Standard-MySQL Client, dem man per Pipe einen Datenstrom reinschiebt echo datenstrom | mysql […] oder aber eine Datei lesen lasst mysql […] < datei. Und wenn Du mit den Netzwerk-Limits nicht leben kannst, dann schieb die Daten als Datei auf den Server und kippe diese dann über eine Socketverbindung, also via localhost in den Server.

        Klingt Interessant, da werde ich mich mal schlau lesen, Danke.

        Gruß

        Jo