ebody: LOAD DATA LOCAL INFILE liest nur 4819 von 4877 Zeilen

Hallo,

per PHP Script lese ich eine XML Datei aus. Einzelne Werte aus jedem Datensatz werden bearbeitet und als String gespeichert. Der String wird in einer CSV gespeichert. Die CSV importiere ich mit diesem Code in die Datenbank.

		$sqlQueryImport = "LOAD DATA LOCAL INFILE '".$fileNewDataImportInDB."' INTO TABLE `" .$sqlTableName."`"
		. " CHARACTER SET UTF8"
		. " FIELDS TERMINATED BY ';'"
		. " ENCLOSED BY '\"'"				
		. " LINES TERMINATED BY '\n'";

Es werden verschiedene XML -> CSV Dateien auf diese Weise in die Datenbank importiert und es funktioniert auch alles bis auf eine CSV. In der CSV sind 4877 Zeilen enthalten, importiert werden aber nur 4819. Die CSV habe ich bzgl. fehlenden Semikolons, Umbrüchen, Anführungszeichen geprüft, konnte aber nichts finden.

Ich habe auch mal testweise nur die letzen 25 Zeilen in der CSV gelassen und sie wurden alle importiert.

Woran könnte es liegen, dass nur 4819 von 4877 Zeilen importiert werden? Gibt es evtl. eine Begrenzung für LOAD DATA LOCAL INFILE?

Gruß ebody

  1. In der CSV sind 4877 Zeilen enthalten, importiert werden aber nur 4819. Die CSV habe ich bzgl. fehlenden Semikolons, Umbrüchen, Anführungszeichen geprüft, konnte aber nichts finden.

    Ich habe auch mal testweise nur die letzen 25 Zeilen in der CSV gelassen und sie wurden alle importiert.

    4877-25 ist aber nur 4852. Ich würde die letzten 4877-4819+1=59 Zeilen drin lassen und mir die erste davon sehr genau ansehen.

    Das aber erst nach einem Blick ins error-log und zwar von php als auch der Datenbank - von dem Du nichts erwähnt hast.

    Gibt es evtl. eine Begrenzung für LOAD DATA LOCAL INFILE?

    Das ẁird eher nicht brechen, denn da handelt es sich bei MySQL um Grenzen des Dateisystems. Aber wie lange darf Dein php-Skript laufen? Platte voll? ...

    Noch was: Zeilen in der Datei sind unter Umständen keine Zeilen aus CSV-Sicht. Was wenn ein Zeilenumbruch in den Daten, also zwischen "" vorkommt?

    1. In der CSV sind 4877 Zeilen enthalten, importiert werden aber nur 4819. Die CSV habe ich bzgl. fehlenden Semikolons, Umbrüchen, Anführungszeichen geprüft, konnte aber nichts finden.

      Ich habe auch mal testweise nur die letzen 25 Zeilen in der CSV gelassen und sie wurden alle importiert.

      4877-25 ist aber nur 4852. Ich würde die letzten 4877-4819+1=59 Zeilen drin lassen und mir die erste davon sehr genau ansehen.

      Das aber erst nach einem Blick ins error-log und zwar von php als auch der Datenbank - von dem Du nichts erwähnt hast.

      Gibt es evtl. eine Begrenzung für LOAD DATA LOCAL INFILE?

      Das ẁird eher nicht brechen, denn da handelt es sich bei MySQL um Grenzen des Dateisystems. Aber wie lange darf Dein php-Skript laufen? Platte voll? ...

      Noch was: Zeilen in der Datei sind unter Umständen keine Zeilen aus CSV-Sicht. Was wenn ein Zeilenumbruch in den Daten, also zwischen "" vorkommt?

      Ich habe auch mal 59 Zeilen probiert, funktioniert. Ich habe auch nur mal ein paar Zeilen in der CSV gelassen die zuvor nicht importiert wurden, wurden aber alle importiert.

      Log Files war ein guter Hinweis, habe ich bisher nie genutzt. Allerdings konnte ich nichts "verdächtiges" finden.

      Mein Script hatte ein set_time_limit(90); habe es jetzt auf set_time_limit(360); gesetzt, kein Unterschied.

      Es ist genug Platz auf der Festplatte.

      Zeilen bzgl. Umbrüchen hatte ich schon überprüft, hier scheint alles ok zu sein. Ich habe die CSV auch mal in Excel geladen, hier werden alle 4877 Zeilen sauber dargestellt.

      Die CSV habe ich testweise noch direkt über PHPMyAdmin importiert, aber auch hier werden nur 4819 Datensätze importiert. Hier hat der Import recht lange gedauert (ca. 2 Min.), während der Import über das Script 2 Sekunden dauert.

      Es gibt/gab keine Fehlermeldung, weder in PHPMyAdmin noch im Script.

      Ich habe auch nochmal die Feldeigenschaften bzgl. Zeichenlänge überprüft, aber das passt eigentlich alles.

      Die CSV ist 827 KB groß.

      In der php.ini stehen folgende Werte, die evtl. relevant sein könnten:

      • upload_max_filesize=1000M
      • max_execution_time=90
      • max_input_time=60
      • memory_limit=1100M
      • error_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICT

      In der my.ini stehen folgende Werte, die evtl. relevant sein könnten:

      • [mysqld]
      • key_buffer = 16M
      • max_allowed_packet = 1M
      • sort_buffer_size = 512K
      • net_buffer_length = 8K
      • read_buffer_size = 256K
      • read_rnd_buffer_size = 512K
      • myisam_sort_buffer_size = 8M
      • ...
      • innodb_buffer_pool_size = 16M
      • innodb_additional_mem_pool_size = 2M
      • ...
      • [mysqldump]
      • quick
      • max_allowed_packet = 16M
      • ...
      • [isamchk]
      • key_buffer = 20M
      • sort_buffer_size = 20M
      • read_buffer = 2M
      • write_buffer = 2M
      • [myisamchk]
      • key_buffer = 20M
      • sort_buffer_size = 20M
      • read_buffer = 2M
      • write_buffer = 2M

      Gruß ebody

      1. Das sollte ausreichen. Geh zu meiner anderen Antwort weiter.

  2. ebody,

    bist Du sicher, dass Du mit deinem PHP Script eine gültige UTF-8 Datei erzeugst? Da PHP der Umgang mit Multibyte-Zeichensätzen nicht in die Wiege gelegt wurde, kann sowas schonmal schiefgehen.

    Besonderes Augenmerk muss man auf Zeichen richten, die in der Latin-1 Codepage (ISO 8859-1) einen Code zwischen 0x80 und 0xFF haben. Die müssen in einer UTF-8 Datei bereits in zwei Bytes dargestellt werden.

    Rolf

    1. ebody,

      bist Du sicher, dass Du mit deinem PHP Script eine gültige UTF-8 Datei erzeugst? Da PHP der Umgang mit Multibyte-Zeichensätzen nicht in die Wiege gelegt wurde, kann sowas schonmal schiefgehen.

      Besonderes Augenmerk muss man auf Zeichen richten, die in der Latin-1 Codepage (ISO 8859-1) einen Code zwischen 0x80 und 0xFF haben. Die müssen in einer UTF-8 Datei bereits in zwei Bytes dargestellt werden.

      Rolf

      Da ich nicht so viel Routine bzgl. PHP und MySQL habe, will ich nicht ausschließen, dass u.a. so etwas möglich ist. Wenn ich die CSV in notepad++ öffne ist sie aber ut8-8 ohne BOM kodiert.

      Wenn ich unter Ansicht > Nicht druckbare Zeichen > Alle Zeichen anzeigen aktiviere, wird alles gleich dargestellt. Also alle Umbrüche, Tabs etc. sehen gleich aus, es gibt keine Reihe, wo ein Unterschied zu sehen wäre.

      Könnte es dennoch bzgl. utf-8 und etwas was nicht wirklich utf-8 ist Probleme geben, weil man es nicht sehen würde?

      Gruß ebody

  3. Denkfehler: die Sätze, die nicht verarbeitet werden können, sind nicht zwangsläufig am Ende der Datei!

    primary key Verletzung? unique Verletzung?

    Such mal mit Excel nach Dubletten.

    1. primary key Verletzung? unique Verletzung?

      Dann könnte also auch das hier helfen: http://php.net/manual/de/mysqli.error.php

      Oder man führe das Theater mal in einer ssh-sitzung (Putty?), alternativ mit einem dem mysql-client in der Konsole/Terminal/cmd aus, falls der MySQL-Server über eine öffentliche IP erreichbar ist.

  4. In der CSV war ein Wert mit einem ": wert1;"wert2;wert3

    Entferne ich diese Zeile aus der CSV werden alle anderen 4876 Zeilen importiert.

    In der XML sah der Wert so aus: xmlWert=""wert2"

    Seltsamerweise wurde das " dann vom Script in der CSV in ein " umgewandelt, während andere Werte wie xmlWert="Firma XYZ & Söhne" genauso in der CSV eingetragen wurden.

    Ich werde jetzt erstmal im Script eine Anpassung vornehmen und alle Sonderzeichen mit http://php.net/manual/de/function.html-entity-decode.php umschreiben. Jeder Wert der ein " enthält, wird ergänzt. In diesem Beispiel sähe das so aus: wert1;"""wert2";wert3

    Ich hoffe das funktioniert. Danke an alle für eure Hilfe und Hinweise.

    Gruß ebody