mysql/mariadb Backup Benutzer erstellen

Zum Backup aller mysql Datenbanken braucht es einen Benutzer, der auf alle Datenbanken Zugreifen kann. Die Backups mit dem root User zu machen ist dafür aber keine Gute Idee.
Welche Berechtigungen braucht ein mysql Backup Benutzer denn mindestens um seine Aufgabe ausführen zu können? Dieser Artikel gibt darüber Auskunft.

Continue reading mysql/mariadb Backup Benutzer erstellen

mysql: Wildcard Zugriffsrechte für Datenbanken

Möchte man einem mysql/mariadb Benutzer automatisch Zugriff auf alle Datenbanken geben, die auf ein bestimmten Muster zutreffen (z.B. alle Datenbanken, welche mit jdoe_ beginnen) geht das ganz einfach mit dem Konstrukt privileges on wildcard name (username\_%):

Continue reading mysql: Wildcard Zugriffsrechte für Datenbanken

Volles Unicode in MySQL Datenbanken

MySQL hatte lange Zeit Probleme mit Zeichensätzen; der bekannte Zeichensalat (auch „Mojibake“ genannt) war die Folge. Dann kam endlich der universelle Zeichensatz Unicode, bzw. UTF8. Praktisch verborgen blieb jedoch bis heute, dass MySQL standardmässig nur einen „beschränkten Unicode Zeichensatz“ verwendet. Dieser besteht nur aus 3, anstelle von 4 Zeichen und war wohl ursprünglich als „Performace-Optimierung“ gedacht.

Das reicht zwar für die allermeisten Schriftzeichen und Symbole, beispielsweise aber nicht für die mittlerweile sehr häufig verwendeten emojis. Schlimmer noch, probiert man ein solches Zeichen (z.B. ein emoji) in die Datenbank einzufügen, wird alles was nach dem Zeichen kommt abgeschnitten. Und das kann wiederum zu schlimmen Sicherheitslücken führen.

Dabei hatte MySQL seit etwa 2010 einen „neuen“ (bzw. den vollen) UTF8-Zeichensatz eingeführt mit dem Namen: utf8mb4.

Neuere Web-Applikationen, wie WordPress oder Typo3 verwenden diesen seit einiger Zeit standardmässig, allerdings nur bei einer Neuinstallation. Viele ältere Datenbanken haben also noch den unvollständigen Zeichensatz eingestellt. Höchste Zeit also die alten Datenbanken mit dem richtigen Unicode Zeichensatz zu aktualisieren.

Continue reading Volles Unicode in MySQL Datenbanken

mysql general query log einschalten

Wenn man einen Vorgang in der mysql/mariadb Datenbank debuggen will, kann es nützlich sein, sämtliche Queries die mysql macht zu loggen. Dies geht mit dem general query log, welches mit diesen drei Zeilen in der /etc/mysql/server.cnf erreicht wird:

log_output=FILE
general_log
general_log_file=/var/log/mysql/queries.log

Aber Achtung: Dies kan enorm viel loggen und ist somit sowohl für die Performance, wie auch Festplatte eine grosse Belastung. Das sollte unbedingt nur kurzzeitig zum Debuggen eines Problems aktiviert. und danach wieder deaktiviert werden.

Bareos: Backup Clients umbenennen

Will man einmal die hostnamen seiner Clients im Netzwerk umbenennen und somit auch die Client-Namen in der bareos Konfiguration entsprechend anpassen muss man vorsichtig sein: Denn dann sieht Bareos jeden Client als „neu“ an und fängt somit wieder mit einem FULL Backup an. Dies kann je anch Anzahl Clients und/oder Speichermenge zu einem plötzlich heftigen Anstieg des Backup-Speichers führen.

Continue reading Bareos: Backup Clients umbenennen

MySQL Galera Cluster: Specified key was too long; max key length is 767 bytes

Der Grund diese Meldung ist, dass bei MySQL die Gesamtzahl aller UNIQUE/PRIMARY keys 767 Bytes nicht überschreiten darf, wobei bei utf8 drei- und bei utf8mb4 vier Bytes pro Zeichen kommen. Somit dürfte die Gesamtzahl aller UNIQUE/PRIMARY keys 191 Zeichen (767 / 4) pro Tabelle nicht überschreiten.

Continue reading MySQL Galera Cluster: Specified key was too long; max key length is 767 bytes

mysql: Alle Konfigurationsoptionen anzeigen

Leider gibt es keine Option in mysql um sich alle konfigurierten Optionen anzeigen zu lassen.

Mittels folgendem Code kann man dies aber von mysql Abfragen:

{ echo -e "# MYSQL VARIABLES {{{1\n##\n# MYSQL `mysql -V|sed 's,^.*\(V.*\)\, for.*,\1,'` - By: `logname`@`hostname -f` on `date +%c`\n##"; for l in {a..z}; do echo '#'; mysql -NBe "SHOW GLOBAL VARIABLES LIKE '${l}%'" | sed 's,\t,^= ,' | column -ts^ | tr "\n" '@' | eval $(echo "sed '" "s,@\("{a..u}{a..z}"\),\n\n\1,;" "'") | eval $(echo "sed '" "s,@\(innodb_"{a..z}{a..z}"\),\n\n\1,;" "'") | tr '@' "\n" | sed 's,^,# ,g'; done; echo -e "#\n##\n# MYSQL VARIABLES }}}1"; } | tee ~/mysql-variables.log

Quelle: Mysql Export current configuration to a file

mysql Passwort zurücksetzen

Wenn man das root Passwort des mysql Servers vergessen hat, lässt sich dieses wie folgt zurücksetzen:

Zuerst muss man mysql beenden und dann manuell im „safe mode“ starten. Danach kann man sich mit root ohne Passwort anmelden:

/etc/init.d/mysqld stop
mysqld_safe --skip-grant-tables &
 
mysql -uroot

Nun kann das Passwort in mysql neu gesetzt werden:

USE mysql;
 
UPDATE USER SET password=PASSWORD("NeuesPasswort") WHERE USER='root';
 
FLUSH privileges;
 
quit

Zu guter leztzt muss man den manuell gestarteten mysql Prozess wieder killen und kann mysql normal starten. Danach ist ein Login mit dem neuen Passwort wieder möglich:

killall mysqld
 
/etc/init.d/mysqld start
 
mysql -u root -p

mysql: Datenbank-Replikation einrichten

Mittels der mysql Datenbank-Replizierung kann man eine automatisch aktualisierende Kopie einer oder mehreren Datenbanken auf einem anderen Server haben.

Dies hat zwei grosse Vorteile:

  • Man hat eine failover-Datenbank, falls die Haupt-DB down ist
  • Man kann die SELECT Abfragen auf mehren Hosts verteilen und hat so einen Lastausgleich.

Grundsätzliches

mysql sieht vor, dass es einen sog. "Master" Server gibt auf dem die Datenbanken verwaltet werden und ein- oder mehrere "Slave"-Server die immer eine aktuelle Kopie tragen. Allerdings ist es normalerweise nicht möglich updates auch auf dem slave-server zu machen, d.H. die slave server sind eigentlich nur für LESE-, nicht aber für Schreibzugriffe da.

Die Funktionsweise geht so, dass der MASTER-Server sämtliche Anweisungen in ein sog. binlog (mysql-bin) schreibt und an die SLAVES sendet. Der SLAVE schliesslich entscheidet mittels des Parameters "replicate-do-db", welche Datenbanken er repliziert.

Konfiguration

Master

Zuerst setzen wir in der my.cnf des Master-Hosts die folgenden Optionen:

[mysqld]
max_allowed_packet              = 16M
server-id                       = 1
log-bin                         = mysql-bin
expire_logs_days                = 7
max_binlog_size                 = 100M
innodb_flush_log_at_trx_commit  = 1
sync_binlog                     = 1
auto_increment_increment        = 1
auto_increment_offset           = 1

Und startet diesen (neu).

[stextbox id=“note“ caption=“Hinweis: server-id“]Die server-id kann eine beliebige Zahl sein, sie muss aber bei jedem Server unterschiedlich sein.
Damit man also nicht ausversehen zwei hosts die gleiche server-id zuweist, nimmt man am besten dessen IP-Adresse, entfernt die Punkte und nimmt das als server-id.

Wenn also z.B. ein Server die IP-Adresse: 192.168.1.100 hat, dann wäre dessen server-id: 1921681100[/stextbox]

Nun wird ein Benutzer für den slave angelegt:

[root@MASTER ~]# mysql -uroot -p
mysql> GRANT REPLICATION SLAVE ON . TO 'slave'@'%' IDENTIFIED BY 'topsecret';

Slave

Auf dem slave müssen die folgenden Optionen gesetzt werden:

[mysqld]
server-id                       = 2
relay-log                       = mysqld-relay-bin
report-host                     = slave-server01
auto_increment_increment        = 2
auto_increment_offset           = 2
replicate-do-db                 = DB1
replicate-do-db                 = DB2
slave_max_allowed_packet        = 16M
read_only                       = 1

[stextbox id=“note“ caption=“Hinweise“]
auto_increment_increment und auto_increment_offset
Diese Parameter sollten idealerweise einen anderen Wert haben als alle anderen Server, da es sonst Probleme bei den AUTO-INCREMENT Werten geben könnte.

replicate-do-db
Hier wird angeben welche Datenbanken repliziert werden.
ACHTUNG: Für jede Datenbank muss zwingend eine neue Zeile verwendet werden! So etwas wie: „replicate-do-db = DB1, DB2“ würde nicht funktionieren!

slave_max_allowed_packet
Dieser Wert darf beim slave nicht kleiner sein als die Einstellung: read_buffer_size auf dem Server, sonst kann es zu Problemen kommen[/stextbox]

Nun kann man auch den slave starten.

Allerdings müssen nun zuerst die Initial-Daten auf den SLAVE geladen werden.
Dazu erstellen wir auf dem master ein mysqldump:

[root@MASTER ~] mysqldump -uroot -p --master-data --databases DB1 DB2 > slave.sql

Dieses slave.sql wird nun auf den SLAVE Server kopiert und eingespielt, nachdem zuvor die SLAVE-Replikation gestoppt wurde:

[root@SLAVE ~] mysql -uroot -p
mysql> SLAVE STOP;
mysql> quit
 
[root@SLAVE ~] mysql -uroot -p < slave.sql
[root@SLAVE ~] mysql -uroot -p
mysql> CHANGE MASTER TO MASTER_HOST='master-server', MASTER_USER='slave', MASTER_PASSWORD='topsecret';
mysql> SLAVE START;
mysql> SHOW SLAVE STATUS \G;
mysql> quit

Im SLAVE STAUS kann man nun sehen ob die Replikation läuft:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

[stextbox id=“note“ caption=“Slave-Replikation kaputt?“]Es kann ab und zu vorkommen, dass die Replikation auf den slave nicht mehr funktioniert.

Dann reicht es aber, den letzten Schritt (mysqldump auf master laden und auf slave einspielen) zu wiederholen und alles sollte wieder laufen.

Falls das nicht funktioniert muss man auf dem master vor dem dump die Tabellen locken:

[root@SLAVE ~] mysql -e 'slave stop;'
 
[root@MASTER ~] mysql -uroot -p
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS \G
mysql> SYSTEM mysqldump -uroot -p --master-data --databases DB1 DB2 > slave.sql
mysql> UNLOCK TABLES;
mysql> quit

Danach auf dem slave einfügen und MASTER_LOG_FILE / MASTER_LOG_POS mit den Werten aus der Ausgabe vom master füllen:

[root@SLAVE ~] mysql -uroot -p < slave.sql
[root@SLAVE ~] mysql -uroot -p
mysql> CHANGE MASTER TO MASTER_HOST='master-server', MASTER_USER='slave', MASTER_PASSWORD='topsecret', MASTER_LOG_FILE='mysql-bin.000000', MASTER_LOG_POS='00000000';
mysql> SLAVE START;
mysql> SHOW SLAVE STATUS \G
mysql> quit
[root@SLAVE ~] mysql -e 'show slave status\G'

[/stextbox]

Troubleshooting

Slaves klonen

Hat man mehrere slaves und einer fällt aus der Synchronisation (etwa weil ausersehenen auf den slave geschrieben wurde), kann man diesen von einem anderen klonen:

[root@SLAVE1 ~] systemctl stop mysql
[root@SLAVE1 ~] cp -pvR /var/lib/mysql /var/lib/mysql.bak
[root@SLAVE1 ~] rsync -ahv --delere slave2:/var/lib/mysql/ /var/lib/mysql/
[root@SLAVE1 ~] cp -v /var/lib/mysql.bak/data/auto.cnf /var/lib/mysql.bak/data/auto.cnf
[root@SLAVE1 ~] systemctl start mysql

[stextbox id=“warning“ caption=“Achtung gleiche UUID“]
Nebst der server_id, welche einen slave eindeutig kennzeichnet, generiert mysql noch eine UUID für jeden slave, welche in der Datei: auto.cnf im mysql Datenverzeichnis abgelegt wird.
Diese darf beim synchronisieren nicht mit kopiert-, bzw. muss danach entweder gelöscht (danngeneriert mysql eine neue) oder vom Backup rüber kopiert werden.
Ansonsten bekommt man die Meldung: „Slave I/O thread: Failed reading log event“.
[/stextbox]

Quellen