{"type":"rich","html":"<div style=\"width: 640; height: 426; font-family: sans-serif,arial,freesans;\" ><div id=\"shared_container_1493855652\" class=\"shared_container\"><div id=\"shared_header_1493855652\" class=\"shared_header\"><a href=\"https:\/\/voidofxulub.com\/channel\/warzazel\"><img src=\"https:\/\/voidofxulub.com\/photo\/profile\/s\/2\" alt=\"\ud835\udd9c\ud835\udd86\ud835\udd97\ud835\udd9f\ud835\udd86\ud835\udd9f\ud835\udd8a\ud835\udd91\u26e7 (Hubzilla)\" height=\"32\" width=\"32\" loading=\"lazy\" \/><\/a><span><a href=\"https:\/\/voidofxulub.com\/channel\/warzazel\">\ud835\udd9c\ud835\udd86\ud835\udd97\ud835\udd9f\ud835\udd86\ud835\udd9f\ud835\udd8a\ud835\udd91\u26e7 (Hubzilla)<\/a>  wrote the following  <a href=\"https:\/\/voidofxulub.com\/item\/40bcb8d3-0dbf-4372-b332-442d2fe46bbc\">post <\/a><span class=\"autotime\" title=\"2026-03-10T03:35:36+01:00\">Tue, 10 Mar 2026 03:35:36 +0100<\/span><\/span><\/div><div id=\"reshared-content-1493855652\" class=\"reshared-content\"><strong>Hubzilla: Datenbank verkleinern und aufbl\u00e4hen verhindern \u2013 ein Erfahrungsbericht<\/strong><br \/><h1>Hubzilla: Datenbank verkleinern und aufbl\u00e4hen verhindern<\/h1><h2>Ein Erfahrungsbericht<\/h2>\u2605Geschrieben von einem verwundertem Hubzilla-Admin\u2605<br \/><br \/><strong>Hinweis:<\/strong> Alle SQL-Operationen wurden mit Backup durchgef\u00fchrt. Bitte immer zuerst ein Backup der Datenbank erstellen bevor man Eingriffe vornimmt.<br \/><br \/><h3><mark class=\"mark\">Das Problem<\/mark><\/h3>Ich bin Hubzilla-Anf\u00e4nger, meine Instanz habe ich Mitte Februar aufgesetzt. Nach ziemlich genau einem Monat hatte sie bereits eine Gr\u00f6\u00dfe von \u00fcber <strong>3,4 GB<\/strong>, was ja jetzt nicht tragisch ist wenn man bedenkt was alles an importierten Inhalten als Blob gespeichert wird. Aber ich hab mir das mal hochgerechnet und dachte: In 6 Monaten ist so dann mein 20 GB-Datenbankspeicher voll.<br \/><br \/>Der Cron-Job schien also nicht das zu tun was man erwartet, <strong>OPTIMIZE TABLE<\/strong> in MySQL brachte auch nichts. Ich hatte im Admin-Men\u00fc eine Ablaufzeit von 4 Tagen eingestellt, mir schien logisch, jetzt niedriger eingestellt, desto eher werden Inhalte gel\u00f6scht \u2013 aber die Datenbank wuchs trotzdem unaufh\u00f6rlich. Ich dachte, muss ich wohl den \u00f6ffentlichen Stream deaktivieren, was ich aber auch nicht wollte.<br \/><br \/>Nach einer Recherche und Analyse habe ich wohl die Ursache gefunden. Und ich versuche das jetzt mal zu dokumentieren.<br \/><br \/><h3><mark class=\"mark\">Die Ursache: Drei versteckte Probleme<\/mark><\/h3><strong>Problem 1:<\/strong> Das Admin-Men\u00fc setzt den falschen Konfigurationsschl\u00fcssel<br \/>Im Admin-Men\u00fc unter <strong>\/admin\/site<\/strong> kann man eine Ablaufzeit f\u00fcr Inhalte einstellen. Ich hatte dort 4 Tage eingetragen \u2013 in der \u00dcberzeugung, dass alte Fremdinhalte oder eigene nach 4 Tagen gel\u00f6scht werden. Die Formulierung war mit nicht so ganz klar.<br \/>Was das Admin-Men\u00fc wirklich tut: Es setzt <strong>default_expire_days<\/strong> und <strong>active_expire_days<\/strong>. Der Expire-Daemon der f\u00fcr f\u00f6derierte Fremdinhalte zust\u00e4ndig ist liest aber <strong>sys_expire_days<\/strong> \u2013 und dieser Wert war bei mir leer, also 0, somit \u201eniemals l\u00f6schen\u201d.<br \/><br \/><strong>Das kann man nur per Kommandozeile pr\u00fcfen:<\/strong><br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system sys_expire_days<\/code><\/pre><br \/><strong>Ergebnis:<\/strong> config[system][sys_expire_days] = (leer!)<br \/><br \/>W\u00e4hrend im Admin-Men\u00fc alles korrekt aussah, hat der Daemon seit Wochen nichts gel\u00f6scht.<br \/><br \/><strong>Problem 2: expire_limit war zu niedrig<\/strong><br \/>Der Expire-Daemon l\u00f6scht standardm\u00e4\u00dfig nur 5.000 Eintr\u00e4ge pro Cron-Lauf. Bei einer Datenbank mit \u00fcber 87.000 angesammelten Remote-Items h\u00e4tte das Monate gedauert \u2013 vorausgesetzt <strong>sys_expire_days<\/strong> w\u00e4re \u00fcberhaupt gesetzt gewesen.<br \/><br \/><strong>Problem 3: InnoDB gibt Speicher nicht automatisch frei<\/strong><br \/>Selbst wenn Eintr\u00e4ge als gel\u00f6scht markiert werden, gibt MySQL\/InnoDB den Speicherplatz nicht automatisch ans Betriebssystem zur\u00fcck. Daf\u00fcr ist <strong>OPTIMIZE TABLE<\/strong> n\u00f6tig \u2013 aber das war ebenfalls deaktiviert.<br \/><br \/><h3><mark class=\"mark\">Die Diagnose<\/mark><\/h3>Zuerst habe ich mir die gr\u00f6\u00dften Tabellen angeschaut:<br \/><br \/><pre><code class=\"language-sql\">SELECT table_name,\nROUND(data_length\/1024\/1024, 2) AS data_mb,\nROUND((data_length+index_length)\/1024\/1024, 2) AS total_mb\nFROM information_schema.tables\nWHERE table_schema = &#039;MEINE_DB&#039;\nORDER BY (data_length+index_length) DESC LIMIT 10;<\/code><\/pre><br \/><strong>Ergebnis bei mir:<\/strong><br \/><a class=\"zrl\" href=\"https:\/\/voidofxulub.com\/photos\/warzazel\/image\/ad63e1a1-a80a-4c15-93cc-18d2a6d3bbef\" target=\"_blank\" rel=\"nofollow noopener\"><img class=\"zrl\" style=\"max-width: 100%;\" src=\"https:\/\/voidofxulub.com\/photo\/ad63e1a1-a80a-4c15-93cc-18d2a6d3bbef-2.png\" alt=\"tabelle1.png\" title=\"tabelle1.png\" loading=\"eager\" \/><\/a><br \/><br \/><strong>Gesamt:<\/strong> \u00fcber <strong>3,4 GB<\/strong> \u2013 und das auf einer kleinen privaten Einzel-Instanz nach 4 Wochen.<br \/>Dann habe ich gepr\u00fcft wie viele Remote-Items sich angesammelt hatten:<br \/><br \/><pre><code class=\"language-sql\">SELECT COUNT(*) FROM item WHERE item_origin = 0;<\/code><\/pre><br \/><strong>-- Ergebnis: 87.633<\/strong><br \/><br \/><pre><code class=\"language-sql\">SELECT COUNT(*) FROM item \nWHERE item_origin = 0 \nAND created &lt; DATE_SUB(NOW(), INTERVAL 5 DAY);<\/code><\/pre><br \/><strong>-- Ergebnis: 64.727 (h\u00e4tten l\u00e4ngst gel\u00f6scht sein sollen!)<\/strong><br \/>64.727 Items die laut meiner Admin-Einstellung h\u00e4tten gel\u00f6scht sein sollen \u2013 aber nie gel\u00f6scht wurden.<br \/><br \/><h3><mark class=\"mark\">Die L\u00f6sung<\/mark><\/h3><h3><mark class=\"mark\">Schritt 1:<\/mark><\/h3> Die fehlenden Konfigurationswerte \u00fcber SSH setzen<br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">cd \/pfad\/zu\/hubzilla<\/code><\/pre><br \/>DER wichtigste Befehl \u2013 das war die Hauptursache:<br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system sys_expire_days 30<\/code><\/pre><br \/>Expire-Limit erh\u00f6hen damit der Daemon schneller arbeitet:<br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system expire_limit 50000<\/code><\/pre><br \/>OPTIMIZE automatisch nach dem L\u00f6schen ausf\u00fchren:<br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system optimize_items 1<\/code><\/pre><br \/>Lieferberichte deaktivieren (f\u00fcr mich unn\u00f6tig, frisst Platz):<br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system disable_dreport 1<\/code><\/pre><br \/>Zur Kontrolle aller Werte:<br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system | grep -i expire<\/code><\/pre><br \/><strong>-- Ausgabe SSH:<\/strong><br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system | grep -i expire<\/code><\/pre><br \/><pre><code>config[system][register_expire] = 3d<br \/>config[system][default_expire_days] = 30<br \/>config[system][active_expire_days] = 30<br \/>config[system][last_expire_day] = 24<br \/>config[system][expire_limit] = 50000<br \/>config[system][sys_expire_days] = 30<\/code><\/pre><br \/><h3><mark class=\"mark\">Schritt 2: Den Expire-Daemon manuell ansto\u00dfen<\/mark><\/h3>Da sich ein R\u00fcckstau angesammelt hatte, habe ich den Daemon manuell mehrfach ausgef\u00fchrt:<br \/><br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php Zotlabs\/Daemon\/Master.php Expire<\/code><\/pre><br \/>Mehrfach wiederholen bis sich kaum noch etwas \u00e4ndert<br \/><br \/><h3><mark class=\"mark\">Schritt 3: Cache und Lieferberichte leeren<\/mark><\/h3><br \/><pre><code class=\"language-sql\">TRUNCATE TABLE cache;\nTRUNCATE TABLE dreport;\n<\/code><\/pre><br \/>Der Cache wird automatisch neu bef\u00fcllt \u2013 das Leeren ist v\u00f6llig sicher.<br \/><br \/><h3>Schritt 4: Bereits gel\u00f6schte Items physisch entfernen<\/h3><br \/><pre><code class=\"language-sql\">DELETE FROM item WHERE item_deleted = 1 LIMIT 50000;\nDELETE FROM item WHERE item_pending_remove = 1 LIMIT 50000;<\/code><\/pre><br \/><h3>Schritt 5: OPTIMIZE ausf\u00fchren<\/h3><br \/><pre><code class=\"language-sql\">OPTIMIZE TABLE item;\nOPTIMIZE TABLE term;\nOPTIMIZE TABLE iconfig;\nOPTIMIZE TABLE cache;\nOPTIMIZE TABLE dreport;<\/code><\/pre><br \/><strong>Hinweis: information_schema<\/strong> zeigt bei InnoDB oft veraltete Gr\u00f6\u00dfen. Die echte Gr\u00f6\u00dfe pr\u00fcft man so (mit eigenem Datenbanknamen anpassen):<br \/><br \/><pre><code class=\"language-sql\">SELECT table_name,\nROUND(data_length\/1024\/1024, 2) AS data_mb,\nROUND(data_free\/1024\/1024, 2) AS free_mb\nFROM information_schema.tables\nWHERE table_schema = &#039;MEINE_DB&#039;\nORDER BY data_length DESC LIMIT 10;<\/code><\/pre><br \/><strong><mark class=\"mark\">Das Ergebnis<\/mark><\/strong><br \/><br \/><a class=\"zrl\" href=\"https:\/\/voidofxulub.com\/photos\/warzazel\/image\/306ff31f-d7ae-4998-850f-d9f218ade7e6\" target=\"_blank\" rel=\"nofollow noopener\"><img class=\"zrl\" style=\"max-width: 100%;\" src=\"https:\/\/voidofxulub.com\/photo\/306ff31f-d7ae-4998-850f-d9f218ade7e6-2.png\" alt=\"tabelle2.png\" title=\"tabelle2.png\" loading=\"eager\" \/><\/a><br \/><br \/><mark class=\"mark\"><span style=\"color: #670000;\"><strong>\u00dcber 2,6 GB eingespart \u2013 mehr als 75% Reduktion<\/strong><\/span><\/mark><br \/><br \/><h3><mark class=\"mark\">Warum passiert das \u00fcberhaupt?<\/mark><\/h3>Hubzilla ist ein f\u00f6deriertes Netzwerk. Jeder Hub speichert Beitr\u00e4ge aus dem gesamten Fediverse lokal \u2013 \u00e4hnlich wie ein E-Mail-Server alle empfangenen Mails speichert. Ohne Ablaufeinstellung w\u00e4chst die Datenbank unbegrenzt.<br \/>Das Problem: Die Ablaufeinstellung im Admin-Men\u00fc (default_expire_days) und der tats\u00e4chlich wirksame Konfigurationsschl\u00fcssel (sys_expire_days) sind zwei verschiedene Dinge. Keine Ahnung warum das so ist, aber es ist zumindest ein Dokumentationsproblem, grade f\u00fcr unbedarfte Admins. Man liest ja auch oft von eben diesem Problem der sich aufbl\u00e4henden Datenbank.<br \/><br \/><h3><mark class=\"mark\">Langfristige Empfehlungen<\/mark><\/h3><strong>Diese Einstellungen sollte man setzen:<\/strong><br \/><br \/><strong>Remote-Inhalte nach 30 Tagen l\u00f6schen<\/strong><br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system sys_expire_days 30<\/code><\/pre><br \/><strong>Schnellere Bereinigung<\/strong><br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system expire_limit 50000 <\/code><\/pre><br \/><strong>Automatisch Speicher freigeben<\/strong><br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system optimize_items 1 <\/code><\/pre><br \/><strong>Lieferberichte deaktivieren<\/strong><br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system disable_dreport 1 <\/code><\/pre><br \/><strong>Und regelm\u00e4\u00dfig pr\u00fcfen:<\/strong><br \/><pre class=\"command-line\" data-prompt=\"$\"><code class=\"language-bash\">php util\/config system | grep -i expire<\/code><\/pre><br \/><h3><mark class=\"mark\">Fazit<\/mark><\/h3>Das Admin-Men\u00fc von Hubzilla suggeriert eine funktionierende Ablaufkonfiguration, die in Wirklichkeit den falschen Konfigurationsschl\u00fcssel setzt. Ohne dieses Wissen kann eine Hubzilla-Instanz \u00fcber Jahre hinweg unkontrolliert wachsen, obwohl man glaubt alles richtig konfiguriert zu haben.<br \/><br \/>\u00dcbrigens zum Schluss am besten im Admin-Men\u00fc die Ablaufzeit auch auf 30 Tage stellen damit alles synchron ist.<br \/><br \/>Ich hoffe dieser Bericht hilft anderen Hubzilla-Admins die das gleiche Problem haben. Aber zum Schlu\u00df nochmal der Hinweis: Ohne Backup der Datenbank keine Befehle einfach nach tippen.<\/div><\/div><br \/><\/div>","width":640,"height":426}