MySQL Server 8 Upgrade Fehler & Hinweise

August 10, 2022 - Lesezeit: 4 Minuten

Mit dem MySQL Server 8, welcher ab Ubuntu 20 LTS Standard ist und auch bei einem System Upgrade installiert wird, wurden einige Server-Variablen entfernt und hinzugefügt.

https://dev.mysql.com/doc/refman/8.0/en/added-deprecated-removed.html

Das kann bei einem Upgrade zu Fehlern führen, sofern man die entfernten Variablen verwendet hat und ggf. lässt sich der Server nicht mehr starten.

In meinem Fall war dies nach einem Upgrade von Ubuntu 18.04 LTS auf Ubuntu 20.04 LTS der Fall.

Die Logdatei unter /var/log/mysql/error.log gab den folgenden Fehler aus:

[Server] unknown variable 'query_cache_limit=1M'.

Also die Variable in /etc/mysql/my.cnf auskommentiert und direkt den nächsten Fehler wegen einer entfernten Variable bekommen:

[Server] unknown variable 'query_cache_size=16M'.

Diese ebenfalls auskommentiert und der MySQL Server ließ sich wieder starten.

Hintergrund: Die beiden Variablen bezogen sich auf den query cache, welcher eine bliebte Methode zum MySQL-Server Performance Tuning war. Seit MySQL 5.7.20 galt dieser aber als veraltet und wurde mit MySQL 8.0 dann komplett entfernt sowie dann auch die Variablen. Wer auf den query cache nicht verzichten kann, findet unter https://proxysql.com/ eine Möglichkeit oder kann diesen auch noch unter MariaDB verwenden. Generell gilt die Entfernung wohl jedoch eher dem Aufruf besseren Code zu schreiben. Ein guter Artikel zu dem Thema findet sich auch hier: https://mysqlquicksand.wordpress.com/2020/05/08/10-reasons-why-mysql-query-cache-should-be-switched-off/


Ein weiteres Problem hatte ich dann mit einem Script, welches einen MSSQL Export als CSV Datei durchführt und diese wieder nach MySQL importiert (siehe auch https://www.le-brice.de/mssql-export-unter-ubuntu-linux). Dazu verwende ich einen MySQL Befehl der auf LOAD DATA LOCAL INFILE zurückgreift:

LOAD DATA LOCAL INFILE 'import.csv' INTO TABLE tablename FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n'

Bei der Verwendung des LOAD DATA LOCAL Statement gibt es seitens der MySQL Entwickler Sicherheitsbedenken, weshalb dieses in MySQL 8 nicht mehr standardmäßig verwendet werden kann. Siehe:

https://dev.mysql.com/doc/refman/8.0/en/load-data-local-security.html

Um das Statement wieder verwenden zu können muss sowohl der MySQL-Server, als auch der verwendete MySQL-Client (in meinem Fall der Standard CLI-Client auf den das Script zurückgreift) die local_infile Variable auf 1 gesetzt haben. Dies kann in der my.cnf unter /etc/mysql/my.cnf geschehen. Der [mysql] Bereich wird sehr wahrscheinlich bereits vorhanden sein, der [client] Bereich ggf. noch nicht und kann am Ende der Konfiguration hinzugefügt werden. Kommentare zur Erinnerung sind empfohlen.

[mysql]
#allow LOAD DATA LOCAL statement on server side
local_infile    = 1
#allow LOAD DATA LOCAL statement on client side
[client]
local_infile    = 1 

Danach den MySQL Server neustarten und das LOAD DATA LOCAL INFILE Statement kann wieder verwendet werden. Übrigens kann man auch die Variable per SQL-Client prüfen:

mysql> show global variables LIKE '%INFILE%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| local_infile  | ON    |
+---------------+-------+
1 row in set (0,00 sec)

mysql>

Da es sich hier, abhängig von der Serververwendung und Umgebung, um eine durchaus zu beachtene Sicherheitswarnung handelt empfehle ich den Abschnitt aus der oben genannten Referenz "Restricting Files Permitted for Local Data Loading" zu beherzigen oder ggf. auch das Script umzubauen um nicht mehr auf die Funktion zurückgreifen zu müssen.


MySQL Zufallswert in Spalte eintragen / updaten

März 8, 2018 - Lesezeit: ~1 Minute

Kurzer Schnipsel. Kann durchaus nützlich sein.

Die Basis um einen Zufallswert, der in einem bestimmten Bereich liegt, ist folgende:

SELECT FLOOR(30 + RAND() * 3)

In diesem Fall wird ein Wert zwischen 30 und 32 generiert. Die Addition am Ende muss also immer > 1 des maximal Bereichs sein.

Als komplettes Statement könnte es z.B. so aussehen

UPDATE table_a SET zufallswert = (SELECT FLOOR(30 + RAND() * 3))


MySQL Daten aus Tabelle löschen zu denen keine ID in anderer Tabelle exisiert

Januar 9, 2017 - Lesezeit: ~1 Minute

Wer halbwegs darauf achtet das seine MySQL Datenbanken nicht völlig zugemüllt sind, der wird früher oder später auch mal Datensätze löschen müssen. Dabei kommt es zumindest bei mir oft vor das ich vor allem Daten aus Tabellen löschen will, zu denen der Nutzer gar nicht mehr existiert. Optimalerweise entfernt man natürlich alle Datensätzes eines Nutzers sobald man diesen aus dem System entfernt, aber auch da kann es Situationen geben wo dies nicht geht oder wo man es aus diversen Gründen vergessen hat. Mit dem folgenden Befehl enterne ich Datensätze zu denen kein Nutzer mehr existiert. Wichtiger Hinweis: Bevor man einen DELETE Befehl ausführt sollte man ein Backup machen oder mit Transactions arbeiten. Ich übernehme keine Verantwortung für verlorene Daten.

DELETE FROM table_a
WHERE user_id
NOT IN (SELECT user_id FROM users)

Hier werden einfach aus tablea alle Daten gelöscht die einer userid zugeordnet sind, die nicht mehr in der Tabelle users existiert.