Ankündigung

Einklappen
Keine Ankündigung bisher.

Allowed memory size exhausted

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Allowed memory size exhausted

    Hallo beisammen!

    Ich sichere meine MySQL-Tabellen über ein PHP-Script, das via Cronjob alle 8 Stunden aufgerufen wird.
    Das hat die letzen Monate wunderbar funktioniert.

    Aber seit heute um 13 Uhr läuft die Sicherung nicht mehr durch.
    Der letzte Erfolgreiche Aufruf war heute Nacht um 04:55 Uhr.
    Beim nächsten um 12:55 Uhr brach die Sicherung nach ein paar Tabellen ab.

    Meldung:
    Fatal error: Allowed memory size of 104857600 bytes exhausted (tried to allocate 14682616 bytes) in /kunden/222772_84172/....php on line 105

    Ich habe jetzt verschiedenste Tests laufen lassen und interessant ist dabei, dass die Sicherung auffallend früh abbricht.
    Schon nach 27 Dateien/Tabellen - die gesamte Sicherung, die heute Nach noch durchlief hat dagegen 47 Dateien/Tabellen.

    HIer das Script, welches ich für die Sicherung verwende - wie gesagt, daran wird's wohl nicht liegen, aber vielleicht ist es hilfreich:

    PHP-Code:

        mysql_query
    ("SET NAMES 'utf8'");
        
    $tables '*';

        
    //get all of the tables
        
    if($tables == '*')
        {
            
    $tables = array();
            
    $result mysql_query('SHOW TABLES');
            while(
    $row mysql_fetch_row($result))
            {
                
    $tables[] = $row[0];
            }
        }
        else
        {
            
    $tables is_array($tables) ? $tables explode(',',$tables);
        }
        
    $return='';

        
    //cycle through
        
    foreach($tables as $table)
        {
            if (
    $table != 'Messages' AND $table != 'Listen_Elemente') {

                
    $result mysql_query('SELECT * FROM '.$table);
                
    $num_fields mysql_num_fields($result);

                
    $return.= 'DROP TABLE '.$table.';';
                
    $row2 mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
                
    $return.= "\n\n".$row2[1].";\n\n";

                for (
    $i 0$i $num_fields$i++) 
                {
                    while(
    $row mysql_fetch_row($result))
                    {
                        
    $return.= 'INSERT INTO '.$table.' VALUES(';
                        for(
    $j=0$j<$num_fields$j++) 
                        {
                            
    $row[$j] = addslashes($row[$j]);
                            
    $row[$j] = str_replace("\n","\\n",$row[$j]);
                            if (isset(
    $row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
                            if (
    $j<($num_fields-1)) { $return.= ','; }
                        }
                        
    $return.= ");\n";
                    }
                }
                
    $return.="\n\n\n";
                
    //save file
                
    $filename 'backup/db-backup-'.$table.'-'.date("Y-m-d-H-i-s"time()).'.sql';
                
    $handle fopen($filename,'w+');
                
    fwrite($handle,$return);
                
    fclose($handle);
                echo 
    '<br/><b>'.$table.'</b> <span style="color:gray;">('.$filename.')</span>';
                
    $return "";

            }

        } 

    Bevor ich mich jetzt daran mache, das Problem zu umgehen (in dem ich z.B. das Backup in mehrere Teile aufgliedere) wollte ich fragen, ob sich bei DF irgend etwas geändert hat.

    Weiß da jemand etwas?

    Ich finde es so seltsam, dass so plötzlich diese Meldung zur Speicherbegrenzung kommt, wo es doch ein paar Stunden vorher noch funktioniert hat ...

    Danke und herzliche Grüße
    Anton


    #2
    Hallo Herr Korduan,
    leider kann ich nur mutmaßen wo die Zeile "105" in der von Ihnen geposteten Script-Referenz zu finden ist.

    Ich habe aber trotzdem folgende Theorie:
    Wenn Sie alle Tabellen, Strukturen und Inhalte in eine Variable schreiben (RAM), dann könnte Ihr Arbeitsspeicher nicht ausreichen. PHP führt eine Beschränkung für die Arbeitsspeicherbelegung „memory_limit“. Es sind einfache Daten bzw. Zeilen hinzugekommen die das Limit sprengen.

    Ich würde Ihnen raten, dass Sie den SQL-DUMP über die Konsole „mysqldump -uuser -ppass databasename > dump.sql“ und einen separaten Nutzer erzeugen (der nur lesen kann). Hier werden auch Indezes sowie sonstige nützliche Infos mitgesichert. Ein Dump ohne Index- und Fremdschlüssel-Informationen ist nicht sehr wertvoll.

    Beispiel Crontab:
    30 11 * * * mysqldump -uuser -ppass databasename > /home/nutzer/backups/dump.sql

    Beste Grüße
    Chris
    Zuletzt geändert von Christian; 22.12.2019, 10:12.

    Kommentar


      #3
      Ich würde auch zu würben Standard wie mysqldump raten. Wenn das damit auch nicht geht den Hoster kontaktieren. Dann kann dieser sich nicht rausreden, dass es am von dir erstellten Skript liegt.

      Kommentar


        #4
        Danke für die Tipps, Christian und Gast

        Ja, dn en Mysqldumper nutze ich bereits. Mir geht es um ein zusätzliches Backup, das einfach ganz simpel die Tabellen direkt als .sql-Datei auf den Server schreibt.

        Ich nehme aber auch starkt an, dass es am Arbeitsspeicher des Servers liegt - dann werde ich mein Script einfach aufteilen und in mehreren Blöcken laufen lassen.

        Die Zeile 105 ist übrigens folgende (sorry, das hätte ich gleich mit angeben sollen):
        PHP-Code:
        if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; } 
        Jetzt teste ich das mal mit dem Aufteilen des Backups.
        Und falls es da wider Erwarten doch noch hakt, melde ich mich hier nochmal.

        Danke!

        Herzliche Grüße
        Anton

        Kommentar


          #5
          Guten Abend Herr Korduan,
          in Ihrer Zeile 105 befüllen Sie die Variable "return". Laut der Fehlermeldung belegt Dump via PHP ca. 14 MB und PHP "GESAMT" darf ca. 104 MB nutzen.

          Ich vermute, dass Sie mehrere Speicherfresser betreiben. Sie könnten die PHP - Einstellung "memory_limit“ erhöhen. Doch diese Lösung ist nicht für die Ewigkeit.

          Auch eine Dump-trennung wird irgendwann wieder das Limit sprengen. Mit dem Dump über die Console sind Sie auf der sicheren Seite. Ich habe bereits oben beschrieben, dass der Dump mehr als nur Struktur und Daten enthält. Ich nehme fest an, dass Ihre Tabellen auch Indexarten (wie zum Besipiel BTree) oder Fremdschlüssel (mit Verhalten) führen. Wenn Sie die Datei-Größe zwischen mysqldump und den Scriptdump vergleichen, dann wird der mysqldump vermutlich größer als der Scriptdump sein.

          Vielleicht hilft Ihnen dieser Tipp:
          Rufen Sie ihr Dump-Script ausschließlich via Cli/ Command Line Interface / Console auf: ~#: "php dumpscript.php > mein-dump.sql" und verwenden Sie direkt die Ausgabe,
          Das heißt "echo '"'.$row[$j].'"'" statt $return.= '"'.$row[$j].'"' ;.

          Sie belegen keinen weiteren Speicher und die Ausgabe wird in eine Datei umgeleitet.

          Beste Grüße
          Chris von 365Layouts

          Kommentar


            #6
            Hmmm ... nein, leider ist da irgend etwas anderes faul.

            Habe mir das nochmal genauer angesehen;

            Das mit dem Arbeitsspeicher klingt zwar einleuchtend.
            Aber mir fällt auf, dass die Sicherung ja bereits nach 27 Dateien (von insgesamt 47) abbricht.

            Das ist mittendrin - da muss sich etwas am Arbeitsspeicher geändert haben.
            Denn in so kurzer Zeit sind die Datenmengen sicher nicht dermaßen stark gewachsen.

            An der Scriptlaufzeit kann es scheinbar nicht liegen:

            Wenn ich das Script normal laufen lasse (hier im Debug-Modus, da werden dei Scipt-Laufzeiten ausgegeben), endet es nach 19 Sekunden:
            (Nicht wundern, die Zeilenzahl des Fehlers ändert sich optisch, wegen der neuen Infos, die ich ausgebe etc.)

            Klicken Sie bitte auf die Grafik für eine vergrößerte Ansicht

Name: 1.jpg
Ansichten: 734
Größe: 225,1 KB
ID: 3528


            Bemerkenswert: Wenn ich dann aber die ersten 10 Tabellen überspringe, dann bleibt es an der selben Strelle hängen, bereits nach 8 Sekunden:

            Klicken Sie bitte auf die Grafik für eine vergrößerte Ansicht

Name: 2.jpg
Ansichten: 710
Größe: 155,8 KB
ID: 3529

            Da kann doch nicht die gleiche Menge an Daten verarbeitet worden sein.

            An der letzten / nächsten Tabelle liegt es aber auch nicht, ich habe dann hier beide manuell ausgeschlossen:

            Klicken Sie bitte auf die Grafik für eine vergrößerte Ansicht

Name: 3.jpg
Ansichten: 695
Größe: 158,1 KB
ID: 3530


            Das ist doch seltsam, oder?

            Herzliche Grüße
            Anton


            Kommentar


              #7
              Zitat von Christian Beitrag anzeigen
              Guten Abend Herr Korduan,
              in Ihrer Zeile 105 befüllen Sie die Variable "return". Laut der Fehlermeldung belegt Dump via PHP ca. 14 MB und PHP "GESAMT" darf ca. 104 MB nutzen.

              Ich vermute, dass Sie mehrere Speicherfresser betreiben. Sie könnten die PHP - Einstellung "memory_limit“ erhöhen. Doch diese Lösung ist nicht für die Ewigkeit.

              Auch eine Dump-trennung wird irgendwann wieder das Limit sprengen. Mit dem Dump über die Console sind Sie auf der sicheren Seite. Ich habe bereits oben beschrieben, dass der Dump mehr als nur Struktur und Daten enthält. Ich nehme fest an, dass Ihre Tabellen auch Indexarten (wie zum Besipiel BTree) oder Fremdschlüssel (mit Verhalten) führen. Wenn Sie die Datei-Größe zwischen mysqldump und den Scriptdump vergleichen, dann wird der mysqldump vermutlich größer als der Scriptdump sein.

              Vielleicht hilft Ihnen dieser Tipp:
              Rufen Sie ihr Dump-Script ausschließlich via Cli/ Command Line Interface / Console auf: ~#: "php dumpscript.php > mein-dump.sql" und verwenden Sie direkt die Ausgabe,
              Das heißt "echo '"'.$row[$j].'"'" statt $return.= '"'.$row[$j].'"' ;.

              Sie belegen keinen weiteren Speicher und die Ausgabe wird in eine Datei umgeleitet.

              Beste Grüße
              Chris von 365Layouts
              Ah! Danke für Ihre Antwort, Chris - das hat sich mit meinem Posting überschnitten.

              Mit dem Cli kenne ich mich noch nicht aus - da kann ich mich aber schon einlesen.
              Nur kurz vorab: Kann ich denn so ein Cli-Script schreiben/speichern und dann via PHP aufrufen (statt manuell via Commandline)?

              Kommentar


                #8
                Sie können einzelne PHP-Script immer direkt in der Konsole aufrufen. Sie sollten folgenden zum kennenlernen ausprobieren:

                Schritt 1:
                Öffnen Sie die Konsole (zum Bespiel Putty oder direkt in MacOS Terminal). Danach geben Sie folgendes ein:
                echo '<?php echo "\nTest\n";' > test.php

                Schritt 2:
                Sie habe ein Testscript erzeugt. Mit cat test.php können Sie den Inhalt prüfen.

                Schritt 3:
                Sie können sas script nun mit dem Befehl "php test.php" Ausführen.

                Sie können auch php-Cronjobs einrichten, zum Beispiel via "crontab -e"
                30 11 * * * php testScript.php > augabe-in-datei.txt

                Kommentar


                  #9
                  Danke Ihnen nochmal, Christian

                  Ich tue mich nur schwer mit der Konsole, das ist totales Neuland für mich.
                  Außerdem möchte ich das gerne komplett automatisieren.

                  Hat ja bisher auch super geklappt: alle 8 Stunden wurden die Tabellen einzeln in .sql-Dateien gesichert, der Ordner wurde automatisch bereinigt, so dass nur die letzten 7 Tage vorgehalten wurden - perfekt.

                  Nur jetzt kommt auf einmal dieses Speicherlimit daher ... :-(

                  Auch der MySQL-Dumper ist natürlich eine Lösung, ich muss ihn nur neu installieren wg. PHP7.
                  Und da sind dann eben immer diese großen ZIP-Dateien, die einzelnen .sql waren mir einfach lieber.

                  Hm ... blöd.
                  Weiß noch nicht, wie ich das jetzt lösen kann.

                  Muss wohl noch weiter recherchieren, wie ich per PHP die Tabellen weniger speicherbelastend exportieren kann.

                  Kommentar


                    #10
                    Da reicht leider manchmal 1 Datensatz aus. Man merkt ja sonst nicht wie nah man ans Limit kommt.
                    Ich schließe mich da dem Tipp von Christian an.
                    Nutze lieber mysqldump via exec(). Du musst das Ding ja auch nicht zippen, auch wenn das wegen dem Platz empfehlenswert ist.

                    Wo nutzt du denn das Script? Auf einem eigenen Server, SharedHosting, JiffyBox?
                    Bei JiffyBox/ManagedServer kannst du es abschalten bzw. abschalten lassen.
                    Im SharedHosting kannst du das über einen Cronjob der das Script direkt aufruft erst mal beheben. Dort gelten dann nämlich 3 mal (afair) höhere Scriptlimits.

                    Kommentar


                      #11
                      Danke Lukas M. ,

                      ich verwende das Script direkt in meiner eigenen PHP-Anwendung.

                      Habe gerade dies hier gefunden:


                      Das funktioniert wunderbar.
                      *freu*


                      Kommentar

                      Lädt...
                      X