diff --git a/README.md b/README.md index 8fd58c7..0919daa 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # JTL-Shop MariaDB Optimization -Automatisierte Index-Optimierung und FULLTEXT-Suche für JTL-Shop-Datenbanken auf Multi-Shop-Servern. +Automatisierte Index-Optimierung, FULLTEXT-Suche und MariaDB-Konfiguration für JTL-Shop-Datenbanken auf Multi-Shop-Servern. ## 🎯 Problemstellung @@ -73,7 +73,7 @@ Das Skript `mariadb-optimization.py` behebt diese Probleme automatisiert: | **2** | Standard-Indizes | Erstellt 4 fehlende Index-Typen | | **3** | FULLTEXT-Index | Erstellt FULLTEXT-Index auf `tartikel` | | **4** | Einstellung aktivieren | Setzt `suche_fulltext = 'Y'` | -| **5** | Rollback-Skript | Generiert Rollback für Notfälle | +| **5** | MariaDB-Config | Erstellt optimierte Konfiguration & Restart | ### Erstellte Indizes @@ -95,6 +95,81 @@ CREATE FULLTEXT INDEX idx_tartikel_fulltext ON tartikel (cName, cSeo, cSuchbegriffe, cArtNr, cKurzBeschreibung, cBeschreibung, cBarcode, cISBN, cHAN); ``` +### MariaDB-Konfiguration (Phase 5) + +Das Skript erstellt automatisch eine optimierte Konfiguration unter: +``` +/etc/mysql/conf.d/ZZ-ztl-final-override.cnf +``` + +**Dynamische Buffer Pool Berechnung:** +- Ermittelt Gesamtgröße aller Datenbanken +- Berechnet: `DB-Größe × 1.2`, aufgerundet auf ganze GB +- Beispiel: 18.74 GB × 1.2 = **23 GB** Buffer Pool + +**Konfigurationsinhalt:** + +```ini +[mysqld] +# InnoDB Buffer Pool (dynamisch berechnet) +innodb_buffer_pool_size = XXG +innodb_buffer_pool_instances = 16 +innodb_buffer_pool_dump_at_shutdown = 1 +innodb_buffer_pool_load_at_startup = 1 +innodb_log_file_size = 512M +innodb_log_buffer_size = 64M +innodb_flush_log_at_trx_commit = 2 + +# InnoDB Performance +innodb_flush_method = O_DIRECT +innodb_file_per_table = 1 +innodb_io_capacity = 2000 +innodb_io_capacity_max = 4000 +innodb_read_io_threads = 16 +innodb_write_io_threads = 16 + +# Query Cache deaktiviert (bei MariaDB 10.1.7+ empfohlen) +query_cache_type = 0 +query_cache_size = 0 + +# Table Cache für viele Shops +table_definition_cache = 20000 +table_open_cache = 15000 +open_files_limit = 30000 + +# Performance +skip_name_resolve = 1 +optimizer_search_depth = 0 +key_buffer_size = 64M + +# Slow Query Log +slow_query_log = 1 +slow_query_log_file = /var/log/mysql/slow.log +long_query_time = 1.0 +log_queries_not_using_indexes = 0 + +# Connections +max_connections = 400 +thread_cache_size = 100 +wait_timeout = 120 + +# Buffer für JTL-Queries +join_buffer_size = 4M +sort_buffer_size = 4M +read_buffer_size = 2M +read_rnd_buffer_size = 2M +``` + +**Wichtige Einstellungen erklärt:** + +| Parameter | Wert | Funktion | +|-----------|------|----------| +| `innodb_buffer_pool_dump/load` | 1 | Buffer Pool bleibt nach Restart "warm" | +| `skip_name_resolve` | 1 | Schnellere Verbindungen (kein DNS-Lookup) | +| `optimizer_search_depth` | 0 | Auto-Optimierung für JOINs | +| `key_buffer_size` | 64M | Reduziert (nur für MyISAM, JTL nutzt InnoDB) | +| `query_cache` | OFF | Bei write-heavy Workloads kontraproduktiv | + ## 🚀 Installation & Verwendung ### Voraussetzungen @@ -124,7 +199,7 @@ python3 mariadb-optimization.py ⚠️ **Zu Zeiten geringer Last ausführen** (nachts/früh morgens) -Der FULLTEXT-Index auf großen Shops (z.B. 468.000 Artikel) kann mehrere Minuten dauern und erhöht kurzzeitig die Server-Last. +Der FULLTEXT-Index auf großen Shops (z.B. 468.000 Artikel) kann mehrere Minuten dauern und erhöht kurzzeitig die Server-Last. Am Ende wird MariaDB automatisch neugestartet. ## 📁 Ausgabe-Dateien @@ -133,7 +208,8 @@ Nach der Ausführung werden folgende Dateien erstellt: | Datei | Zweck | |-------|-------| | `/root/jtl_search_backup_TIMESTAMP.json` | Backup aller Sucheinstellungen | -| `/root/jtl_search_rollback_TIMESTAMP.py` | Rollback-Skript | +| `/root/jtl_search_rollback_TIMESTAMP.py` | Rollback-Skript für Sucheinstellungen | +| `/root/mariadb_config_backup_TIMESTAMP.cnf` | Backup der vorherigen MariaDB-Config | | `/root/jtl_index_log_TIMESTAMP.txt` | Vollständiges Ausführungs-Log | ## 🔄 Rollback bei Problemen @@ -143,6 +219,10 @@ Falls nach der Optimierung Probleme auftreten: ```bash # Rollback der Sucheinstellungen (setzt suche_fulltext auf vorherigen Wert) python3 /root/jtl_search_rollback_TIMESTAMP.py + +# Rollback der MariaDB-Konfiguration +cp /root/mariadb_config_backup_TIMESTAMP.cnf /etc/mysql/conf.d/ZZ-ztl-final-override.cnf +systemctl restart mariadb ``` **Hinweis:** Die erstellten Indizes müssen nicht zurückgerollt werden – sie haben keine negative Auswirkung und können bei Bedarf manuell entfernt werden. @@ -180,6 +260,22 @@ Typische Gründe: 2. Updates erstellen keine Indizes nachträglich 3. Die Tabellen waren ursprünglich klein +### Wie wird der Buffer Pool berechnet? + +``` +Buffer Pool = Gesamtgröße aller Datenbanken × 1.2 (aufgerundet) +``` + +Beispiel: 18.74 GB × 1.2 = 22.49 GB → **23 GB** + +### Warum ist Query Cache deaktiviert? + +Bei Multi-Shop-Servern mit vielen Schreiboperationen (Bestellungen, Lagerbestände, etc.) ist der Query Cache kontraproduktiv: + +- Jedes INSERT/UPDATE/DELETE invalidiert den Cache +- Lock Contention bei vielen gleichzeitigen Queries +- MySQL 8.0 hat den Query Cache komplett entfernt + ### Wie kann ich den Effekt messen? **Vorher/Nachher Vergleich:** @@ -219,7 +315,7 @@ pt-query-digest --limit=50 /var/log/mysql/slow.log > /tmp/slow_report.txt ```bash # Shops ohne FULLTEXT-Index -mysql -N -e "SELECT t.table_schema, t.table_rows +mysql -N -B -e "SELECT t.table_schema, t.table_rows FROM information_schema.tables t WHERE t.table_name = 'tartikel' AND t.table_schema NOT IN ( @@ -230,14 +326,31 @@ AND t.table_schema NOT IN ( ORDER BY t.table_rows DESC;" # FULLTEXT-Einstellung pro Shop -mysql -N -e "SELECT table_schema FROM information_schema.tables +mysql -N -B -e "SELECT table_schema FROM information_schema.tables WHERE table_name = 'teinstellungen'" | while read db; do - val=$(mysql -N -e "SELECT cWert FROM \`$db\`.teinstellungen + val=$(mysql -N -B -e "SELECT cWert FROM \`$db\`.teinstellungen WHERE cName = 'suche_fulltext' LIMIT 1" 2>/dev/null) echo "$db: ${val:-NICHT GESETZT}" done ``` +### Datenbankgrößen prüfen + +```bash +# Gesamtgröße aller Datenbanken +mysql -N -B -e "SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) +FROM information_schema.tables +WHERE table_schema NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys');" + +# Größe pro Datenbank +mysql -e "SELECT table_schema AS 'Datenbank', +ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Größe (MB)' +FROM information_schema.tables +WHERE table_schema NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys') +GROUP BY table_schema +ORDER BY SUM(data_length + index_length) DESC;" +``` + ### Buffer Pool & Key Metrics ```bash @@ -247,54 +360,6 @@ mysql -e "SHOW GLOBAL STATUS WHERE Variable_name IN 'Threads_running','Questions','Slow_queries','Uptime');" ``` -## 📋 Empfohlene MariaDB-Konfiguration - -Basierend auf der Analyse, hier eine optimierte Konfiguration für Multi-Shop-Server: - -```ini -[mysqld] -# InnoDB Buffer Pool (ca. 70% des verfügbaren RAM) -innodb_buffer_pool_size = 32G -innodb_buffer_pool_instances = 16 -innodb_log_file_size = 512M -innodb_log_buffer_size = 64M -innodb_flush_log_at_trx_commit = 2 - -# InnoDB Performance -innodb_flush_method = O_DIRECT -innodb_file_per_table = 1 -innodb_io_capacity = 2000 -innodb_io_capacity_max = 4000 -innodb_read_io_threads = 16 -innodb_write_io_threads = 16 - -# Query Cache deaktiviert (bei MariaDB 10.1.7+ empfohlen) -query_cache_type = 0 -query_cache_size = 0 - -# Table Cache für viele Shops -table_definition_cache = 20000 -table_open_cache = 10000 -open_files_limit = 30000 - -# Slow Query Log -slow_query_log = 1 -slow_query_log_file = /var/log/mysql/slow.log -long_query_time = 1.0 -log_queries_not_using_indexes = 0 - -# Connections -max_connections = 400 -thread_cache_size = 100 -wait_timeout = 120 - -# Buffer für JTL-Queries -join_buffer_size = 4M -sort_buffer_size = 4M -read_buffer_size = 2M -read_rnd_buffer_size = 2M -``` - ## 🐛 Bekannte Einschränkungen ### Nicht durch Indizes lösbar