Regina Schaukrug: Grafiken in Datenbank speichern? Ein Beispiel dafür, wie man das vermeiden kann.

Beitrag lesen

Der Mitleser schrieb

Bilder/Videos & Co in 99% der Fälle ins Dateisystem.

Vermutlich hat er mit "& Co." statisches Zeug gemeint, welches nicht durchsucht wird, eine gewisse Größe hat (512 Byte, also Standard-Blockgröße vieler Geräte wäre schon mal ein Anhaltspunkt) und über Key-Value-Abhängigkeit geholt werden kann(Key als Bestandteil des Dateinamens).

Er hat aus meiner Sicht die von die angeführten HTML-Templates nicht ausgeschlossen. Mit dem "warum nur" willst Du vom Mitleser eine Begründung für etwas, was er nicht behauptet hat.

Es gibt jede Menge Entwickler die speichern text/html Dateien massenweise in Datenbanken und nehmen die von Dir genannten Nachteile offensichtlich gerne in Kauf. Wobei es programmiertechnisch gar keinen Unterschied gibt ob ein HTML Template oder ein GIF aus MySQL gelesen wird.

Des Pudels Kern ist doch das hier: "nehmen die von Dir genannten Nachteile offensichtlich gerne in Kauf". Wenn ich einen Nachteil in Kauf nehme, dann doch nur wenn ich dadurch einen Vorteil habe, der den Nachteil überwiegt. Ob ich mich bei den unbekannten Projekten der von Dir genannten anonymen Entwickler deren Meinung anschließen würde, dass die Vorteile die Nachteile überwiegen, steht in den Sternen.

Ganz generell würde ich dazu neigen, Bilder ins Dateisystem zu legen. Ein guter Grund die in einer Datenbank abzulegen könnte z.B. eine Datenanreicherung mit durchsuchbaren Meta-Daten und geforderte referentielle Integrität (Hier: "Bild nicht löschbar, wenn in Nachricht enthalten") sein. Doch selbst dann muss man überlegen, ob die Grafik wirklich in eine Datenbank muss:

Ein Beispiele dafür, dass das trotz teilweiser "referentieller Integrität" nicht sein muss:

Nehmen wir mal eine Nachrichtenseite. Aus irgendwelchen Gründen soll die Gesamtgröße der Daten unter /var/www/htdocs (dto:/var/lib/mysql, die Ordner sind nur ein Beispiel) eine gegebene und knappe Größe nicht überschreiten. Jetzt sollen also irgendwann Nachrichten gelöscht werden (können), damit Platz für neue Nachrichten wird. So der Plan (hoffentlich bevor die Seite erstellt wurde, 3 Jahre am Netz und der Platz wegen der 10000 Nachrichten mit 25000 Bildern - zusammen sind das bei 40 KB pro Bild rund 1 GB - knapp ist...).

Zu den Nachrichten gehören jeweils kein, ein oder einige Fotos. Die Fotos wieder können zu einer oder mehreren Nachrichten gehören.

Jetzt stellt sich die Frage, wie man sicherstellt, dass Nachrichten und NUR die nicht mehr verwendeten Fotos gelöscht werden. Mit der Datenbank ist das relativ einfach und man könnte sagen "Ok. Ich nehme hier die Nachteile der Speicherung in der Datenbank in Kauf."

Kommt die Regina Schaukrug vorbei, und sagt: "Wieso? Das Dateisystem ist "(NoSQL-Datenbank genug" Das geht also auch anders:"

  • Das Bild kommt nach /var/www/image-dir/bild.png.
  • Wenn es von einer Nachricht benutzt wird, dann wird auf dem Dateisystem ein "harter Link" angelegt, welcher im Name einen Hinweis auf die Nachricht (hier: "nachricht-0815") und natürlich einen Zähler (hier: 3) enthält:
ln /var/www/image-dir/bild.png /var/www/htdocs/image-dir/nachricht-0815-03.png

Der Link-Zähler der Datei /var/www/image-dir/bild.png steht jetzt auf 2, der Speichermehrverbrauch? Ein paar handverlesene Bytes.

-rw-r--r-- 2 USER GROUP 7582 Okt  7 12:21 bild.png

Mit etwas wie

ls -l bild.png | cut -d " " -f2

bekommt man übrigens die 2, also den Linkzähler. In PHP mit:

echo lstat('bild.png')['nlink'];

Wenn man die Nachricht löscht, dann löscht man auch die Links zu den zugehörigen Bildern:

rm -f  /var/www/htdocs/image-dir/nachricht-0815-*.png;

Der Linkzähler steht im Beispiel jetzt auf 1.

-rw-r--r-- 1 USER GROUP 7582 Okt  7 12:21 bild.png

Das Löschen nicht mehr verlinkter, also nicht benötigter Bilder ist dann mittels Shell-Befehl einfach:

cd  /var/www/image-dir;
find -name "*.png" -links 1 -exec rm -f "{}" \;;

findet jedes Bild, welches nur einen Link hat, also in keiner Nachricht mehr vorkommt und löscht es, auf das, wie gefordert Licht Platz werde. Sollten extrem viele Bilder gelöscht werden müssen, dann

find -name "*.png" -links 1 -print0 |  xargs -0 rm -f

(Mit z.B. PHP geht es auch, ist halt nur etwas aufwändiger…)

Wenn jetzt aber der Kunde kommt und irgendwas erzählt, dass das aber völlig betriebssystemunabhängig, "meinetwegen mit MsDOS" funktionieren soll, dann würde ich sagen "Er will es nicht schnell und günstig sondern langsam, aufwendig und kompliziert. Ab in die Datenbank mit dem Zeug! Viel Spaß mit MsDOS, dem Webserver, der Datenbank und der unabhängigen Skriptsprache!"

Falls der Kunde aber die Idee gut oder gut genug findet würde ich ihn darauf hinweisen, dass beim Backup mit rsync die Option "-H" gesetzt werden muss und dass natürlich niemand einen Artikel oder eine Nachricht anlegen darf, während die alten gelöscht werden. (Das kann man übrigens auch "programmtechnisch" sicherstellen.)