MySQL
1. Benutzerverwaltung
1.1 Benutzer anzeigen
-- einfache Übersicht
SELECT User, Host
FROM mysql.user;
-- inkl. Authentifizierungsinformationen (nicht direkt bearbeiten!)
SELECT User, Host, plugin, authentication_string
FROM mysql.user;
Hinweis: Die Tabelle
mysql.usersollte nur gelesen werden.
Benutzer immer mitCREATE USER,ALTER USERundGRANTverwalten.
1.2 Benutzer anlegen und Berechtigungen vergeben
Anmeldung als Administrator:
mysql -u root -p
Datenbank anlegen:
CREATE DATABASE DBNAME
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
Benutzer nur lokal (localhost):
CREATE USER 'DB_USER'@'localhost'
IDENTIFIED BY 'DB_PASS';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER
ON DBNAME.* TO 'DB_USER'@'localhost';
Benutzer mit Zugriff von überall (nicht empfohlen):
CREATE USER 'DB_USER'@'%'
IDENTIFIED BY 'DB_PASS';
GRANT ALL PRIVILEGES
ON DBNAME.* TO 'DB_USER'@'%';
Wichtig: Seit MySQL 8 wird ein Benutzer nicht mehr implizit über
GRANT ... IDENTIFIED BYangelegt: zuerstCREATE USER, dannGRANT.
1.3 Benutzeranmeldung
Lokal:
mysql -u DB_USER -p DBNAME
Anmeldung an einem entfernten Host:
mysql -u superadmin -p -h intranet-prod-mysql.irgendwas.com confluencedbtemp
1.4 Benutzer löschen
DROP USER IF EXISTS 'DB_USER'@'localhost';
DROP USER IF EXISTS 'DB_USER'@'%';
2. Datenbanken und Schemata
2.1 Datenbank erstellen
CREATE DATABASE ecg_otrs_intern_test
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
2.2 Datenbank löschen
DROP DATABASE db_name;
2.3 Schemagröße anzeigen
SELECT table_schema,
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS total_mb
FROM information_schema.tables
GROUP BY table_schema
ORDER BY total_mb DESC;
3. Remote-Zugriff
3.1 Server für Remote-Zugriff konfigurieren
Standardmäßig lauscht MySQL/MariaDB nur auf 127.0.0.1.
Typische Konfigurationsdateien:
/etc/mysql/mysql.conf.d/mysqld.cnf
MariaDB: /etc/mysql/mariadb.conf.d/50-server.cnf
Beispiel:
[mysqld]
# bind-address = 127.0.0.1 # Standard
# Variante 1: nur interne Adresse
bind-address = 10.0.0.5
# Variante 2: alle Interfaces (nur mit Firewall/VPN!)
# bind-address = 0.0.0.0
Dienst neu starten:
systemctl restart mysql
Warnung:
bind-address = 0.0.0.0ohne Firewall oder VPN ist ein deutliches Sicherheitsrisiko.
3.2 Benutzer für Remote-Zugriff freischalten
Bereits vorhandene Benutzer mit Remote-Hosts anzeigen:
SELECT User, Host
FROM mysql.user
WHERE Host <> 'localhost';
Beispiele:
-- Benutzer mit Vollzugriff von einem bestimmten Host
CREATE USER 'echomike'@'ecgwin64.vngag.de'
IDENTIFIED BY 'neuesPasswort';
GRANT ALL PRIVILEGES ON *.* TO 'echomike'@'ecgwin64.vngag.de'
WITH GRANT OPTION;
-- Benutzer mit Zugriff aus einem Subnetz
CREATE USER 'user_otrs'@'10.96.%.%'
IDENTIFIED BY 'otrs4test';
GRANT ALL PRIVILEGES ON ecg_otrs_intern_test.* TO 'user_otrs'@'10.96.%.%'
WITH GRANT OPTION;
Hinweis:
GRANT ALL ON *.* WITH GRANT OPTIONnur sehr sparsam und nur für Admin-Konten verwenden.
4. Backup & Restore mit mysqldump
4.1 Gesamten Server sichern
mysqldump -u root -p --single-transaction --all-databases > dump.sql
4.2 Einzelne Datenbank(en) sichern
# eine Datenbank
mysqldump -u root -p --single-transaction DBNAME > DBNAME.sql
# mehrere Datenbanken
mysqldump -u root -p --single-transaction --databases db1 db2 > multi.sql
Beispiel mit Datumsstempel:
mysqldump -u otrs -p otrs \
> /tmp/otrs-$(date +%Y%m%d-%H%M).sql
Hinweis:
--single-transactionist für InnoDB der Standardweg, um konsistente Dumps zu erzeugen, während Anwendungen weiter schreiben können.
4.3 Restore eines Dumps (klassisch, ohne Docker)
mysql -u BENUTZER -p DATENBANK < datenbank.sql
Beispiel:
mysql -u root -p dfsgwhh < dump.sql -v
Hinweis:
-v(--verbose) zeigt den Fortschritt ausführlicher an.
Warnung: Bei Dumps mit
--all-databaseswird auch die Systemdatenbankmysqlmit Benutzerkonten und Rechten überschrieben.
4.4 Dump mit Fortschrittsanzeige
apt install pv
pv dump.sql.gz | zcat | mysql -u user -p database
4.5 Dump per Cron (Beispiel mit Docker-Container)
crontab -e
# Zabbix database backup
2 0 * * * /srv/zabbix/cron/mysqldump.sh >/dev/null 2>&1
/srv/zabbix/cron/mysqldump.sh:
#!/bin/bash
USER=zabbix
PASSWORD=PASSWORD
OUTPUT="/srv/exx/tmp_dbdumps/"
CONTAINER=zabbix-db
DATABASE=zabbix
DATE=$(date +%Y-%m-%d)
[email protected]
HOSTNAME=$(cat /proc/sys/kernel/hostname)
# Backup-Verzeichnis anlegen
if [ ! -d "$OUTPUT" ]; then
mkdir -p "$OUTPUT"
fi
rm -f "$OUTPUT"/zabbix*
# Dump aus Docker-Container
docker exec "$CONTAINER" \
mysqldump -u "$USER" --password="$PASSWORD" \
--single-transaction "$DATABASE" \
> "$OUTPUT/${DATABASE}_${DATE}.sql"
if [ "$?" -eq 0 ]; then
rm -f /srv/exx/z_backups/*.*
cp "$OUTPUT"/zabbix* /srv/exx/z_backups/
echo "DB Backup erfolgreich"
else
echo "$HOSTNAME - DB Backup $DATABASE - $DATE fehlgeschlagen" | \
mail -s "$HOSTNAME - DB Backup $DATABASE - $DATE fehlgeschlagen" -- "$MAILTO"
fi
4.6 Restore, wenn MySQL/MariaDB im Docker-Container läuft
Bei MySQL/MariaDB im Docker-Container wird der Restore über docker exec ausgeführt.
Das < dump.sql passiert auf dem Host, nicht im Container.
4.6.1 Einzelne Datenbank in einem Container zurückspielen
Beispiel:
docker exec -i zabbix-db \
mysql -u zabbix --password=PASSWORD zabbix \
< /srv/exx/z_backups/zabbix_2025-01-01.sql
Hinweis:
-istreamt den Dump über stdin in den Containerzabbix-dbist der Containernamemysql -u zabbix ... zabbixverbindet sich auf die Datenbank zabbix
Der Dump wurde typischerweise mit:
mysqldump -u zabbix -p --single-transaction zabbix > zabbix_2025-01-01.sql
erstellt und enthält keinen CREATE DATABASE.
4.6.2 Kompletten Server-Dump (--all-databases) zurückspielen
docker exec -i mysql-db \
mysql -u root --password=ROOTPASS \
< /pfad/zu/dump-all.sql
Hinweis:
Dump enthält alle Datenbanken inkl.
mysql(Benutzer und Rechte) Für vollständige Neuinstallation geeignet, sonst kritisch
4.6.3 Datenbank vor dem Restore neu anlegen/aufräumen
# Datenbank im Container neu anlegen
docker exec mysql-db \
mysql -u root --password=ROOTPASS \
-e "DROP DATABASE IF EXISTS confluencedb;
CREATE DATABASE confluencedb
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;"
# Dump in die frisch angelegte DB einspielen
docker exec -i mysql-db \
mysql -u root --password=ROOTPASS confluencedb \
< /pfad/zu/confluencedb.sql
4.6.4 Restore aus einem separaten Client-Container
Alternative über einen eigenen MySQL-Client-Container im selben Docker-Netzwerk:
docker run --rm -i --network=my-net \
-v /srv/backups:/backups \
mysql:8 \
mysql -h mysql-db -u root --password=ROOTPASS confluencedb \
< /srv/backups/confluencedb.sql
Hinweis:
--network=my-net: gemeinsames Docker-Netzwerk/srv/backups: Host-Verzeichnis mit Dumps
4.6.5 Typische Fehlerquellen
→ Benutzer/Passwort/Host (User@Host) prüfen "Unknown database …"
→ Datenbank anlegen oder prüfen, ob der Dump
CREATE DATABASE enthält
Container nicht erreichbar→
docker ps, Docker-Netzwerk, Ports und Firewall prüfen
4.6.6 Alte MySQL-Daten im Docker-Setup aufräumen
Wenn eine MySQL-/MariaDB-Instanz im Docker-Setup komplett verworfen und "frisch" neu aufgebaut werden soll, kann das gemountete Datenverzeichnis auf dem Host gelöscht werden.
Achtung:
Danach sind alle Daten und Benutzer endgültig gelöscht Nur machen, wenn ein verlässlicher Dump existiert Pfad und Volume-Mapping genau kontrollieren
Beispiel (Volume auf ./data/mysql):
# Container stoppen
docker compose stop joomla_db
# Datenverzeichnis entfernen (zerstörerisch!)
rm -rf ./data/mysql
# Container mit leerem Datenverzeichnis neu starten
docker compose up -d joomla_db
Beim nächsten Start initialisiert MySQL/MariaDB die Systemtabellen neu.
Anschließend kann ein Dump wie oben beschrieben eingespielt werden.
5. Binary Logging
5.1 Konfiguration (MySQL < 8.4 / MariaDB)
[mysqld]
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 2
max_binlog_size = 50M
5.2 MySQL 8.4 und neuer
expire_logs_days ist entfernt, stattdessen:
[mysqld]
log_bin = /var/log/mysql/mysql-bin.log
binlog_expire_logs_seconds = 172800 # 2 Tage
max_binlog_size = 50M
Zum Deaktivieren des Binary Logging log_bin auskommentieren/entfernen
(nur tun, wenn keine Replikation / Point-in-Time-Recovery benötigt wird).
6. Konfiguration (my.cnf / .my.cnf)
6.1 MySQL/MariaDB-Konfigurationsdateien
Typische Orte:
/etc/mysql/my.cnf (Hauptdatei mit Includes)
/etc/mysql/mysql.conf.d/mysqld.cnf (MySQL-Server)
/etc/mysql/mariadb.conf.d/50-server.cnf (MariaDB-Server)
6.2 Persönliche Client-Konfiguration (~/.my.cnf)
Erlaubt Login ohne Passwort auf der Kommandozeile:
[client]
host = localhost
user = root
password = 123456
[mysqldump]
user = root
password = 123456
Sicherheit:
Datei auf den jeweiligen Benutzer beschränken:
chmod 600 ~/.my.cnfFür produktive Umgebungen besser dedizierte Backup-User mit eingeschränkten Rechten nutzen
6.3 Root-Passwort ändern
Moderne Variante (MySQL 5.7+/8.x, MariaDB):
ALTER USER 'root'@'localhost'
IDENTIFIED BY 'NeuesSicheresPasswort';
Ältere Variante mit mysqladmin:
mysqladmin -u root -p password
Bei Distributionen mit auth_socket-Plugin kann zuvor ein Wechsel des Plugins nötig sein.
6.4 mysql_upgrade (nur Altversionen)
Ältere MySQL-Versionen:
mysql_upgrade -u root -p -h localhost
Hinweis:
Bis MySQL 8.0.15 relevant Seit 8.0.16 wird das Schema beim Serverstart automatisch aktualisiert In neueren Versionen ist
mysql_upgradeentfernt
7. Monitoring mit mytop
mytop zeigt laufende Queries ähnlich wie top.
Installation (Debian/Ubuntu):
apt install mytop
Verwendung:
mytop -d mysql
8. Nützliche SQL-Befehle (Beispiel Mailserver)
8.1 Datenbank auswählen
USE mailbase;
8.2 Tabellen anzeigen
SHOW TABLES;
```
Beispielausgabe:
```
+--------------------+
| Tables_in_mailbase |
+--------------------+
| domains |
| mailusers |
| weiterleitungen |
+--------------------+
8.3 Tabelleninhalte anzeigen
SELECT * FROM domains;
```
Beispiel:
```
+----+-----------------------------+
| id | domain |
+----+-----------------------------+
| 1 | irgendwas.de |
| 2 | nochwas.de |
+----+-----------------------------+
8.4 Datensätze einfügen
INSERT INTO mailusers
SET account = '[email protected]',
maildir = 'irgendwas.de/p.meier',
home = '/var/spool/maildirs',
password = 'DevCiphEqu',
angelegt_von = 'm.müller',
angelegt_am = CURDATE();
INSERT INTO weiterleitungen
SET forward_from = '[email protected]',
forward_to = '[email protected]',
angelegt_von = 'm.müller',
angelegt_am = CURDATE();
Hinweis: In realen Mail-Setups werden Passwörter in der Regel gehasht gespeichert.
8.5 Suchen
-- exakte Suche
SELECT * FROM weiterleitungen
WHERE forward_from = '[email protected]';
-- unscharfe Suche mit LIKE
SELECT * FROM weiterleitungen
WHERE forward_from LIKE '%pressestelle%';
```
Beispielausgabe:
```
+-----+-------------------------------+----------------------------+--------------+-------------+----------+
| id | forward_from | forward_to | angelegt_von | angelegt_am | memo_txt |
+-----+-------------------------------+----------------------------+--------------+-------------+----------+
| 751 | [email protected] | [email protected] | m.müller | 2015-09-08 | |
+-----+-------------------------------+----------------------------+--------------+-------------+----------+
8.6 Löschen
DELETE FROM weiterleitungen
WHERE id = 751;
8.7 Werte ändern
UPDATE weiterleitungen
SET angelegt_von = 'k.lehmann'
WHERE forward_from = '[email protected]';
9. Hinweise zu Locks während mysqldump
Früher:
Genauer:
--single-transaction und bei MyISAM-Tabellen werden Tabellen gesperrt (Schreibzugriffe blockiert)
Mit --single-transaction und InnoDB können Anwendungen weiter schreiben, während mysqldump einen konsistenten Snapshot liest
Für moderne Installationen mit InnoDB ist:
mysqldump --single-transaction ...
die Standardempfehlung.