Benjamin Keil: PHP, Daten speichern: Datenbank vs. Ascii-File

Hallo zusammen,

ich habe im letzten halben Jahr ein wenig in MySQL
hereingeschnuppert und für mich festgestellt, dass
es doch bei 'kleineren' Datenmengen zu aufwendig ist.
Probleme, auf die ich gestossen bin waren z.B.
die Preise der Provider, aufwändiges db-design,
installieren von php-my-admin, backup und wiederherstellung
der daten zu kompliziert für kunden, usw...

Ich habe mir bei kleineren Datenmengen,
z.B. Gästebuch oder persönliche Einstellungen, folgendes angewöhnt:

Eine Datei, die per include geladen wird - Beispiel:

gaestebuch.dat
---
<?php

$entries = array(
 1 => array ("Name", "Text", "IP");
 2 => array ("Name", "Text", "IP");
 3 => array ("Name", "Text", "IP");
);

?>
---

Mich würde interessieren, ob Ihr das so für sinnvoll haltet,
ob es schneller als eine Datenbank ist und wie Ihr mit solchen
Daten umgeht. Wenn es in Euren Augen Sinn macht, wo ist
dann die Grenze, ab der man eine Datenbank braucht?

In meinem Fall sind meistens Daten, die oft, z.B. mit foreach ausgegeben werden, aber nur selten geändert werden.

So eine Datei ist ja für die meisten Laien noch gut
'verstehbar' und den Umgang mit einem FTP-Programm
kann man ja auch fast jedem beibringen.

Schöne Grüße aus Freiburg,

Ben

  1. Hallo,

    Eine Datei, die per include geladen wird

    Mich würde interessieren, ob Ihr das so für sinnvoll haltet,

    Sicher, wenn deine Daten für nichts anderes verwendet werden, als zum Erzeugen einer schicken HTML Ausgabe (Gästebuch) oder ähnlichem, dann ist deine Lösung so völlig in Ordnung.

    ob es schneller als eine Datenbank ist und wie Ihr mit solchen
    Daten umgeht. Wenn es in Euren Augen Sinn macht, wo ist
    dann die Grenze, ab der man eine Datenbank braucht?

    Was die Geschwindigkeit angeht, da kann ich dir nichts genaues sagen, da ich keine Vergelichswerte kenne. Aber das einlesen der Datei würde ich rein gefühlsmäßig für schneller halten, da die ganze Geschichte mit der Verbindung zum MySQL Server (welcher die Daten dann auch erst einmal suchen muss) wegfällt.

    Sinnvoll ist eine Datenbank sicher dann, wenn du mit deinen Daten mehr machen willst, als sie einfach blos auszugeben. Wenn du in einer MySQL Datenbank mehrere Tabellen hast, die alle in einer Recht komplexen Suche eingeschlossen sind, um dann dein gewünschtes Ergebnis zu liefern, dann wäre es schon ziemlich verrükt, das alles über eine Speicherung in text/plain nachzubasteln.

    In meinem Fall sind meistens Daten, die oft, z.B. mit foreach ausgegeben werden, aber nur selten geändert werden.

    Hier wäre eine Datenbank wirklich erst dann sinnvoll, wenn die Datenmengen überhand nehmen. Eine include Datei mit einer Dateigröße von 1 Gigabyte (als Extrembeispiel), welche vollgestopft mit Gästebucheinträgen ist, komplett einzulesen, blos um die ersten 15 Einträge auszugeben, das wäre sicher nicht mehr die ideale Lösung.

    Aber solange dein System gut funktioniert und die Datenmengen nicht zu groß werden, solange würde ich auch nichts daran ändern.

    Viele Grüße,

    Stefan

    --
    Lass dir das Tanzen NICHT verbieten
    http://tanzverbot.de
    1. Hallo Stefan,

      danke erstmal. Da bin ich beruhigt, mir liegt mehr das
      Gestalten und ein bißchen Dynamik, falls mal was
      größeres mit extremen Suchfunktionen anliegt,
      werde ich mir wohl jemanden zur Hilfe nehmen, zumindest vorerst.

      Was mich noch interessieren würde, angenommen
      mehrere Personen versuchen gleichzeitig über ein
      Webinterface eine solche Datei zu bearbeiten,
      würde das in einer Extremsituation zu einem Fehler führen,
      oder wir bei PHP grundsätzlich einer nach dem anderen
      'abgearbeitet'?

      Gruß,

      Ben

      1. Sup!

        In dem Fall bist Du angearscht. Siehte "Isolation".

        Gruesse,

        Bio

      2. Hallo,

        Was mich noch interessieren würde, angenommen
        mehrere Personen versuchen gleichzeitig über ein
        Webinterface eine solche Datei zu bearbeiten,
        würde das in einer Extremsituation zu einem Fehler führen,
        oder wir bei PHP grundsätzlich einer nach dem anderen
        'abgearbeitet'?

        Das kommt ganz darauf an, wie du es programmiert hast. Nehmen wir einfach mal den einfachsten Fall der Dateibearbeitung: Die Datei wird ausgelsen, in einer textarea zur Verfügung gestellt, dort kann sie geändert werden, über ein Formular wird sie zurückgeschickt und wieder geschrieben.

        Wenn jetzt Person A und Person B beide die Datei bearbeiten wollen, dann haben sie beide die aktuelle Version 1 vor sich. Nun ändern beide etwas, Person A schickt die Änderungen ab und nun ist die Version 2a gespeichert.
        Danach schickt Person B seine geänderte Datei ab. Version 2a wird nun mit Version 2b überschrieben. Die von A gemachten Änderungen sind verloren.

        Du müsstest also sicherstellen, dass keine Änderungen welche Version 1 als Ursprungsdatei hatten die Version 2 Datei überschreiben dürfen.
        Dies könntest du z.B. durch einen Vergleich des letzten Schreibzugriffes o.ä. erreichen.

        Besser wäre es aber wohl immer nur einen geleichzeitigen Benutzer auf des Webinterface draufzulassen. Dazu benötigst du allerdings ein Login-System.

        Viele Grüße,

        Stefan

        --
        Lass dir das Tanzen NICHT verbieten
        http://tanzverbot.de
        1. Hallo Stefan,

          Du müsstest also sicherstellen, dass keine Änderungen welche Version 1 als Ursprungsdatei hatten die Version 2 Datei überschreiben dürfen.

          Das ist ja zum Glück 'nur' eine Frage des Projektmanagements.
          Im Fall des Gästebuches kann ich mir z.B. vorstellen,
          dass der Moderator Kommentare zu Einträgen abgeben und
          ändern kann. Wenn es nun mehrere Moderatoren gibt,
          dann muss sowieso eine Absprache getroffen werden,
          wer für was Zuständig ist. Soetwas muss ja nicht immer
          technisch gelöst werden. Bei anderen Systemen sind
          dann u.U. verschiedene Logins oder sogar ein CVS System
          vorrausgesetzt, aber das wird bei Datenbanken ja auch nicht
          anders sein.

          'Bin immer wieder begeistert wie schnell man hier im Forum
          hilfreiche und versierte Antworten bekommt!
          Ihr seid klasse!!

          Schöne Grüße

          Ben

          1. Hallo,

            Du müsstest also sicherstellen, dass keine Änderungen welche Version 1 als Ursprungsdatei hatten die Version 2 Datei überschreiben dürfen.

            Das ist ja zum Glück 'nur' eine Frage des Projektmanagements.

            Okay, aber bitte sorge dafür, dass du nicht in die oft auftrendene Falle tappst. Wenn dein Script mit einer Schreibaufforderung aufgerufen wird (Eintrag hinzufügen, Kommentar hinzufügen, Eintragstext ändern, Eintrag löschen, ...), dann musst du ja immer folgendes machen:

            1. Die bisherigen Daten aus der alten Datei einlesen
            2. Die Änderung vornehmen
            3. Die geänderte Datei wieder schreiben

            Hierbei musst du unbedingt beachten, dass du die gelockte Datei zwischen 1. und 3. auf keinen Fall schließen darfst. Also nicht für 1. zum Lesen öffnen, 2. ausführen und die Datei dann für 3. erneut zum Schreiben öffnen. Dies wäre ziemlich fatal und würde früher oder später zu Datenverlust führen.

            Viele Grüße,

            Stefan

            --
            Lass dir das Tanzen NICHT verbieten
            http://tanzverbot.de
            1. Hi,

              Hierbei musst du unbedingt beachten, dass du die gelockte Datei zwischen 1. und 3. auf keinen Fall schließen darfst. Also nicht für 1. zum Lesen öffnen, 2. ausführen und die Datei dann für 3. erneut zum Schreiben öffnen. Dies wäre ziemlich fatal und würde früher oder später zu Datenverlust führen.

              Das Tolle an der Beispieldatei ist, dass ich sie
              zum Lesen nicht 'öffnen' muss, sondern einfach includieren,
              daher kann der Fehler nicht auftreten.

              Ben

              1. Hallo Benjamin,

                Das Tolle an der Beispieldatei ist, dass ich sie
                zum Lesen nicht 'öffnen' muss, sondern einfach includieren,
                daher kann der Fehler nicht auftreten.

                Weißt du, dass du mit diesem Satz gerade dein ganzen Konzept tödlich vernichtet hast?
                Du sagst also, dass du nicht locken kannst. Dass heißt dann der Fehler ist da und du kannst ihn nicht verhindern.

                User A und User B wollen sich ins Gästebuch eintragen. Beide schicken ihren Eintrag ab, Instanz 1 und Instanz 2 deines Scriptes werden gestartet.

                Beide haben irgendwo ein include stehen und holen sich die gespeicherten Daten. Beide verarbeiten Parallel jeweils einen Eintrag. User A hat allerdings nicht so viel geschrieben, also ist Instanz 1 vorher fertig, schreibt die neue Datendatei und beendet sich.
                Nun ist Instanz 2 auch mit der Bearbeitung fertig, schreibt ebenfalls die neue Datei (Orginal + Eintrag B) und beendet sich.

                Jetzt hast du deinen Eintrag A verloren. Einleuchtend, oder? Du kannst natürlich darauf hoffen, dass dieser Fall so selten vorkommt, dass es nicht groß stört. Aber sauber programmiert wäre das nicht.

                Viele Grüße,

                Stefan

                --
                Lass dir das Tanzen NICHT verbieten
                http://tanzverbot.de
  2. Sup!

    Die Datei als Lösung hat einige Nachteile:

    1. Bei zunehmender Datenmenge hast Du eine zunehmende Dateimenge und dann irgendwann ein Chaos von kryptisch benannten Dateien
    2. Das Einlesen der Daten dauert zunehmend länger, im schlimmsten Fall sind die gesuchten Daten im letzen Datensatz in der Datei - das belastet das Dateisystem, und auch das RAM, weil die ganze Datei geparst weren muß, und kostet natürlich auch Rechenzeit - irgendwann, bei ein paar hundert oder tausend Einträgen, kommt das zum Tragen
    3. Eine Datenbank garantiert einige Sachen:

    Atomicity (Atomizität): Das Eintragen erfolgt ganz oder gar nicht - wenn Deine Dateien beim Aktualisieren z.B. halb geschrieben werden, und dann der Rechner abstürzt, dann sind einfach Daten weg.
    Consistency (Konsistenz): Die Datenbank weigert sich, falsche Daten anzunehmen, dadurch sind die Daten immer konsistent und wieder auslesbar. Bei Dateien, die am Ende noch vom Benutzer editiert werden können, kann sonstwas drinstehen, und ggf. können kleine Fehler in der Datei das Skript verwirren oder - noch schlimmer - exploiten.
    Isolation: Bei gleichzeitigem Zugriff von mehreren Transaktionen auf die Datenbank werden die Zugriffe von der Datenbank so gehandhabt, daß sie sich nicht in die Quere kommen. Bei Deinen Dateien könnten zwei Benutzer gleichzeitig eine Datei bearbeiten und dann hochladen, und die Änderungen des einen würden verloren gehen. Eine Datenbank würde den Zugriff auf die Daten, die bearbeitet werden, temporär sperren, so daß soetwas nicht vorkommen kann.
    Durability: Die Datenbank führt Logs und speichert die Daten ggf. mehrfach, so daß ein Absturz die Daten nicht zerstört und der Zustand der Datenbank wiederhergestellt werden kann, auch wenn der Rechner mitten im Betrieb kaputt geht. Ein Dateisystem kann es schon mal zerbrezeln.

    Nachteile der Datenbank:

    1. Bei ganz kleinen Datenmengen Overkill
    2. Ggf. teuer
    3. Zugriff etwas schwieriger als Zugriff auf in einer Datei gespeicherte Datenstrukturen - es sei denn, man hat eine objektorientierte Datenbank in Kombination mit persistenten Objekten in einer objektorientierten Sprache

    Die Vorteile der Dateien sind natürlich:

    1. Einfach zu implementieren
    2. Geringe Kosten
    3. Hinreichend für kleines Projekt

    Nachteile:

    1. Haben nicht die Vorteile der Datenbank...

    Gruesse,

    Bio

    1. Hi Bio

      1. Bei zunehmender Datenmenge hast Du eine zunehmende Dateimenge und dann irgendwann ein Chaos von kryptisch benannten Dateien

      Das Problem kann man vorraussehen und umgehen, z.B.
      Dateinamen in Form des aktuellen Datums, das würde mir
      z.B. bei einem extremen Gästebuch eine einfachen Archivierung ermöglichen.

      1. Das Einlesen der Daten dauert zunehmend länger, [...]

      In dem Fall muss ich die Daten auf viele kleine Dateien aufteilen.

      1. Eine Datenbank garantiert einige Sachen:

      Atomicity (Atomizität): Das Eintragen erfolgt ganz oder gar nicht - wenn Deine Dateien beim Aktualisieren z.B. halb geschrieben werden, und dann der Rechner abstürzt, dann sind einfach Daten weg.

      Das würde bedeuten, das Beispiel-Array währe kaput
      und ich kann es nicht mehr einlesen?
      Ein guter Provider müsste doch dann Backups haben,
      sicherlich sinds diese Daten dann einige Stunden oder Tage alt.

      Consistency (Konsistenz): Die Datenbank weigert sich, falsche Daten anzunehmen, dadurch sind die Daten immer konsistent und wieder auslesbar. [...]

      Ich muss doch sowieso grundsätzlich allen Eingaben misstrauen
      und diese auf mögliche Probleme, z.B. HTML-Tags untersuchen.
      Oder meinst Du was anderes? Hättest Du ein kleines Beispiel?

      Isolation: Bei gleichzeitigem Zugriff von mehreren Transaktionen auf die Datenbank werden die Zugriffe von der Datenbank so gehandhabt, daß sie sich nicht in die Quere kommen. Bei Deinen Dateien könnten zwei Benutzer gleichzeitig eine Datei bearbeiten und dann hochladen, und die Änderungen des einen würden verloren gehen. Eine Datenbank würde den Zugriff auf die Daten, die bearbeitet werden, temporär sperren, so daß soetwas nicht vorkommen kann.

      Wieder das Beispiel Gästebuch, angenommen 100 user tragen
      sich innerhalb von einer Sekunde ein. Werden Sie dann
      nicht nacheinander abgearbeitet, also 1. Eintrag
      wird empfangen, *.dat wird gelesen und mit neuem Eintrag
      am Ende neu geschrieben, 2. Eintrag wird empfangen,...

      Durability: Die Datenbank führt Logs und speichert die Daten ggf. mehrfach, so daß ein Absturz die Daten nicht zerstört und der Zustand der Datenbank wiederhergestellt werden kann, auch wenn der Rechner mitten im Betrieb kaputt geht. Ein Dateisystem kann es schon mal zerbrezeln.

      Das dürfte aber ein relativ geringes Risiko sein,
      und mit entsprechender Hardware (wie heissen die Dinger, Raid-Controller ?) teilweise zu umgehen sein?

      Ich bin noch nicht ganz in der Lage das Verhälltniss zwischen
      Aufwand und Sicherheit einer DB abzuschätzen.

      Selbst bei einem Gästebuch währe es ja peinlich wenn
      man eine Fehlermeldung 'Ausser Betrieb' ausgeben muss.

      Grüße,

      Ben

      1. Hallo,

        Das Problem kann man vorraussehen und umgehen, z.B.
        Dateinamen in Form des aktuellen Datums, das würde mir
        z.B. bei einem extremen Gästebuch eine einfachen Archivierung ermöglichen.

        Sicherlich kann man im Endeffekt alles in Dateien packen. (Eine Datenbank macht es ja auch nicht anderst. Irgendwo muss sie ihre Daten auch ablegen.) Aber irgendwann ist deine Implementierung dann so kompliziert geworden (weil du alle möglichen Probleme umgehen willst), dass du gleich eine Datenbank verwenden könntest.

        Das würde bedeuten, das Beispiel-Array währe kaput
        und ich kann es nicht mehr einlesen?
        Ein guter Provider müsste doch dann Backups haben,
        sicherlich sinds diese Daten dann einige Stunden oder Tage alt.

        Sich auf jemand anderen (Provider) zu verlassen ist schon mal keine so gute Idee. Und wie du selbst sagst, das Backup wäre etwas älter. Bei einer Datenbank wäre nur der Datensatz, der gerade hätte geschrieben werden sollen verloren.

        Ich muss doch sowieso grundsätzlich allen Eingaben misstrauen
        und diese auf mögliche Probleme, z.B. HTML-Tags untersuchen.
        Oder meinst Du was anderes? Hättest Du ein kleines Beispiel?

        Hast du nicht vorhin mal aufgeführt, dass so eine Textdatei prinzipiell auch per Hand gepflegt werden könnte. Da kann man sicherlich einiges ausversehen bei kaputtmachen.

        Wieder das Beispiel Gästebuch, angenommen 100 user tragen
        sich innerhalb von einer Sekunde ein. Werden Sie dann
        nicht nacheinander abgearbeitet, also 1. Eintrag
        wird empfangen, *.dat wird gelesen und mit neuem Eintrag
        am Ende neu geschrieben, 2. Eintrag wird empfangen,...

        Die Scripte laufen parallel ab, wenn die Anfragen auch parallel eingingen. Dafür, dass sie sich nicht in die Quere kommen, musst du selbst über locking sorgen. Ich weiß nicht, wie es bei PHP ausschaut, aber bei Perl musst du flock manuell aufrufen, damit du auf der sicheren Seite bist.

        Ich bin noch nicht ganz in der Lage das Verhälltniss zwischen
        Aufwand und Sicherheit einer DB abzuschätzen.

        Selbst bei einem Gästebuch währe es ja peinlich wenn
        man eine Fehlermeldung 'Ausser Betrieb' ausgeben muss.

        Wenn du wirklich ein Gästebuch schreiben wolltest, dann könntest du das mit Textdateien zur Datenhaltung machen oder eine Datenbank verwenden. In diesem Fall würden sich sicher keine erkennbaren Unterschiede für den Anwender zeigen. Programmierfehler können dir bei beiden Varianten unterlaufen, und diese wären wohl mit der größten Wahrscheinlichkeit für das "Außer Betrieb"-sein Schuld.

        Viele Grüße,

        Stefan

        --
        Lass dir das Tanzen NICHT verbieten
        http://tanzverbot.de
        1. Hi,

          Die Scripte laufen parallel ab, wenn die Anfragen auch parallel eingingen. Dafür, dass sie sich nicht in die Quere kommen, musst du selbst über locking sorgen. Ich weiß nicht, wie es bei PHP ausschaut, aber bei Perl musst du flock manuell aufrufen, damit du auf der sicheren Seite bist.

          Ich werde heute Abend mal testen wie PHP das macht,
          es müssten ja dann 2 Scripte auf eine Datei zugreifen.
          Script 1 öffnet die Datei, bekommt eine pause von 30sek.
          sleep(30) vor dem Schließen, ich starte Script 2 und mal schauen ob das 2. vor dem ersten abgearbeitet wird...

          Oder habe ich einen Denkfehler?

          Ben

          1. Hallo,

            Ich werde heute Abend mal testen wie PHP das macht,
            es müssten ja dann 2 Scripte auf eine Datei zugreifen.
            Script 1 öffnet die Datei, bekommt eine pause von 30sek.
            sleep(30) vor dem Schließen, ich starte Script 2 und mal schauen ob das 2. vor dem ersten abgearbeitet wird...

            Lies dir lieber mal http://de3.php.net/manual/en/function.flock.php durch, das beschreibt das locking unter PHP.

            Viele Grüße,

            Stefan

            --
            Lass dir das Tanzen NICHT verbieten
            http://tanzverbot.de