• Jun
  • 03
  • 2010

MySQL Backup Strategien: LVM-Snapshots

Posted by okami In Datenbanken, Featured, Howtos | No Comments »
MySQL Backup Strategien: LVM-Snapshots

Master  – Slave mit LVM

Vorteile

  • Restorezeit ist wesentlich geringer bei großen Datenbanken und vielen Indexen (abhängig von Lese- und Netzwerggeschwindigkeit).
  • Geringe Ausfallzeit des Servers – keine Ausfallzeit des Arbeitsbetrieb
  • Der Master kann unbeeinträchtigt seine Arbeit vortsetzen.

Nachteile

  • “Eben mal” eine Tabelle oder Daten zurückspielen geht nicht, hierzu müssen wir ein kompletten Restore auf ein weiteres System durchführen, um dort mittels mysqldump die Daten zu extrahieren.

Szenario:

Wir benötigen mindestens 2 MySQL Instanzen die miteinander replizieren, damit verringern wir die Ausfallzeit auf 0. Also jedes beliebige Master – Slave oder Master – Master Szenaria, wobei wir am besten einen Slave für das Backup einrichten. Die Slave Instanz kann sich durchaus, wenn es Plattenplatz, CPU, RAM sowie die IO Werte zulassen, auf dem selben Host befinden. Eine Anleitung wie man eine Replikation aufsetzt findet man hier. Natürlich funktioniert das Ganze auch ohne Replikation, allerdings hat man dann, je nach Datenbank, eine Ausfallzeit von 10s – x Minuten. Wichtig, die my.cnf muss so angepasst werden, dass sich die Daten auf einem Logical Volumen (LVM) befinden. Darüber hinaus benötigen wir in der Volumengroup genügend Restplatz, damit uns der Snapshot nicht während des Backups vollläuft. Hier gibt es keine Faustformel das muss man einfach ausrechnen oder probieren.

In meinen Augen hat es sich relativ nützlich erwiesen die Konfiguration der MySQL Instanz wie folgt aufzugliedern:

  1. Das LV wird in ein Verzeichnis gemountet, beispielsweise /data.
  2. Unterhalb dieses Verzeichnisses werden unterschiedliche Verzeichnisse für binlogs, relaylogs, tmp, data sowie error und slowlog angelegt.

Das vereinfacht das Sichern insofern, dass wir hier nur bestimmte Verzeichnisse wegsichern müssen. Es ist auch keine schlechte Idee auf dem Slave das Binlog zu aktivieren und diese ebenfalls zu sichern (z.B. stündlich), damit wir ein sogenanntes Point in Time Recovery machen können (wird an einem späteren Zeitpunkt abgehandelt). Unsere my.cnf sieht dann an den entsprechenden Punkten wie folgt aus:

relay-log                      = /data/mysql-relaylog/relay.log
relay-log-info-file            = /data/mysql-relaylog/relay-log.info
relay-log-index                = /data/mysql-relaylog/relay-log.index
log_error                      = /data/mysql-log/mysql.err
log-slow-queries               = /data/mysql-log/slow_queries.log
log_bin                        = /data/mysql-binlog/mysql-bin.log
innodb_log_group_home_dir      = /data/mysql-data
innodb_log_arch_dir            = /data/mysql-data
innodb_data_home_dir           = /data/mysql-data
datadir                        = /data/mysql-data

Für den Fall, dass wir einen weiteren Slave oder Master wieder herstellen müssen, benötigen wir noch die Postion und das Binlogfile, damit wir die Replikation an diesem Punkt wieder aufsetzen können. Im Prinzip gehen wir im weiteren wie folgt vor: wir stoppen den MySQL Dienst, dann ermitteln wir Binlog File und Position des Masters, legen einen Snapshot an, starten den MySQL Dienst und dann können wir das Backup vom Snapshot starten. Das Vorabscript für den Backup Dienst könnte wie folgt aussehen – bitte beachten, die Pfade und Variablen an die eigene Umgebung anpassen (Volumen und Volumengroupbezeichnungen zum Beispiel).

#!/bin/sh
# Groesse des Snapshots
GROESSE=20G

# Name des Snapshot
NAME=mysql-backup

# Geraetedateiname
# hier das LVS anpassen
GERAET=/dev/db/data

# Mount-Punkt
MOUNT=/backup

# Spiegelgeraet
SPIEGEL=/dev/db/mysql-backup
# Stoppe Datenbank
echo
echo "Shutting down lively database  `date`"
echo
/etc/init.d/mysql stop

#gegebenen Fall diesen Wert anpassen, wenn die Datenbank länger braucht
sleep 3

# Erzeuge Restore Daten für Master - Master
name=$(tail -1 /data/mysql-binlog/mysql-bin.index)
size=$(stat -c '%s' ${name})
echo "binlog Position $name $size" > /data/mysql-data/db_restore.info

# Erzeuge Spiegel
lvcreate --size $GROESSE --snapshot --name $NAME $GERAET
ERGEBNIS1=`echo $?`

if [ $ERGEBNIS1 -ne 0 ]; then
echo
echo
echo "  -- F E H L E R -- "
echo
echo "  Starte Datenbank ohne Backup `date`"
echo
echo
/etc/init.d/mysql start
exit 22
fi

sleep 3

# starte Mysql wieder

echo
echo "Restarting lively database  `date`"
echo
/etc/init.d/mysql start

# pruefe auf mount und mounte Spiegel oder exit

mount | grep /backup
ERGEBNIS2=`echo $?`

if [ $ERGEBNIS2 -eq 0 ]; then
echo
echo
echo "  -- F E H L E R -- "
echo
echo "   Der Mount besteht bereits"
echo
echo
exit 23
else
mount -o ro $SPIEGEL $MOUNT
fi

exit 0

Das Resultat an dieser Stelle sollte ein Read only eingemounteter Snapshot unter /backup sein. Dem Backup Programm weisen wir jetzt nur noch an, die Verzeichnisse:

/backup/mysql-data
/backup/mysql-relaylog

zu sichern.

  • Mai
  • 25
  • 2010

Okami WordPress Theme

Posted by okami In Featured, Sonstiges | 4 Comments »
Okami Wordpress Theme

Nach ein wenig “Herumprobieren”, ist die Roadmap gesteckt und somit ist heute auch die Beta Version 0.2.3 vom okami Theme fertig.

Wichtige Kriterien für mich, sind immer noch neben dem komfortablen Umgang mit der Seite, Ladezeiten (bei DSL 1000 unter 1 Sekunde) und der Verwendung von so wenig wie möglichen grafischen Elementen, sowie Javascript.

Okami ist ein 2 Spalten WordPress Theme(+2.7), voll widgetfähig mit Administrationsbereich und ist  für deutsch, english und japanisch verfügbar.  Im Großen und Ganzen steht das Layout, es wird nur noch marginale Änderungen und Anpassungen geben, sowie weitere Abspeckarbeiten im Code und CSS um die Performance anzuheben.  Des weiteren überlege ich im Footer eine Menü / Kategorie Option einzubauen.

Neben Kommentarfunktionen die Threads unterstützen, können bequem im Administrationsbereich bis zu 4 unterschiedliche Bereiche der Sidebar via Drag’n’Drop konfiguriert werden. Dabei unterstützt das Theme eine Aufspaltung in eine obere und untere breitere Box.  In der Mitte können zwei Boxen mit Menüelementen versehen werden.

Der generierte HTML Code ist w3c validiert, selbiges gilt für das CSS.  Getetstet und geprüft ist das Theme gegen aktuelle Firefoxvarien 3.+, Anpassungen wird es auch noch für IE 6&7 geben – allerdings für keine früheren Browserversionen.

WordPress 2.7+ [okami download] [okami demo]

svn checkout http://okami-wordpress.googlecode.com/svn/trunk/ okami-wordpress-read-only

Changelog:

  • Mai 25,2010 – Release 0.2.3 – Change index.php, single and archive layout. Fixed site templates for new layout. Removed redundant code and pictures.
  • Mai 23,2010 – Change the threaded comment layout .
  • Mai 22, 2010 – Fixed JavaCode, header.php, css – press the websites speed  under 1 second for DSL 1024.
  • Mai 16, 2010 – Release 0.2 – fixed page-templates  and css to get the mix working.
  • Mai 15, 2010 – Cleaned up invalid code caused of mixing the function.php from neutral and piano. Cleaned up styling for nested categories and pages in navigation elements.

Für Feedback, Anmerkungen, Anregungen etc. bin ich immer zu haben. Zu finden gibts das Theme in Zukunft unter der Projektseite: hier

  • Mai
  • 18
  • 2010

MySQL – Recovery

Posted by okami In Datenbanken, Featured | 3 Comments »
MySQL - Recovery

Letztens bekam ich kurzzeitig einen Herzaussetzer, weil ich beim Restore des Datenbankbackups (LVM) bemerkte, dass doch die ib_logfiles nicht mit zurückgesichert wurden. Nachdem ich kurz nachgeschaut und fetsgestellt habe, dass die im Standardverzeichnis unter /var/lib/mysql herumdümpelten und nicht auf dem Logical Volume wo sie gesichert werden, wurde es erstmal finster ums Hirn. Hmm das passiert und zwar jeden Tag und wenn es solche Momente nicht gäbe, wäre ja alles irgendwie zu einfach …

Was tun, sprach Zeus?

Die Antwort findet sich in der MySQL Dokumentation. Allerdings für meine Begriffe völlig zu unrecht in “2 Nebensätzen” abgehandelt und wenn es brennt findet man das sowieso nie. Also aus diesen Anlass hier ein paar hilfreiche Tipps, Tricks und Anwendungsbeispiele um gecrashte, falsch gesicherte und sonstwie misshandelte Tabellen oder MySQL Instanzen wiederherzustellen, aber der Reihe nach.

  • Mrz
  • 20
  • 2010

Replikation mit MySQL 5.x

Posted by okami In Datenbanken, Featured | No Comments »
Replikation mit MySQL 5.x

Master – Slave Replikation:

Szenario:

Replikation aller Datenbanken eines Server zu Backupzwecken auf einen weiteren Server. Achtung: Dies kann auch erreicht werden, indem wir eine zusätzliche Instanz auf unseren vorhanden Server einrichten. Zunächst müssen wir sicherstellen, dass in der my.cnf folgende Einträge wie folgt vorhanden sind:

#bind-address           = 127.0.0.1
muss auskommentiert werden, damit die MySQL Instanz auf den externen Interfaces erreichbar ist

log-bin = /var/log/mysql/mysql-bin.log
hiermit schalten wir das binlog ein, welches zwingen notwendig für die Einrichtung einer Replikation ist, auf dem Slave können wir die Binlogs ebenfalls anschalten. (Backup)

server-id=1
diese IDs müssen auf den an der Replikation beteiligten Servern eingerichtet und unterschiedlich sein

expire_logs_days        = 10
gibt an, ab wieviel Tagen die Logs gelöscht werden

max_binlog_size         = 500M
die maximale Größe eines Binlogs

Danach starten wir MySQL auf dem Server neu:

/etc/init.d/mysql restart

Überprüfe dann mit

netstat -tanp | grep mysql

ob MySQL wirklich auf allen Interfaces hört:

okami:~# netstat -antp | grep mysql
tcp 0 0 *:mysql *:* LISTEN 2671/mysqld

Auf dem Master Server richten wir anschliessend den Benutzer für die Replikation ein:

mysql -u root -p

Führe in der MySQL Kommandozeile folgende Befehle aus:

GRANT REPLICATION SLAVE ON *.* TO ’replikation_user’@'IP_SLAVE’ IDENTIFIED BY ’replikation_passwort’;
FLUSH PRIVILEGES;
quit;

Das weitere Vorgehen ist davon abhängig ob wir schon Daten in der Datenbank haben, oder ob wir die Datenbank erst jungfräulich aufgesetzt haben.

Wenn Master und Slave sozusagen frisch aufgesetzt sind, noch keine Daten existieren, notieren wir auf dem Master Binlog und Binlogposition weg.

SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000009 |      112 |              |                  |
+------------------+----------+--------------+------------------+

Auf dem Slave passen wir die my.cnf wie folgt an:

#bind-address           = 127.0.0.1
server-id = 2

log-bin= /var/log/mysql/mysql-bin.log

relay-log = /var/lib/mysql/slave-relay.log
relay-log-index = /var/lib/mysql/slave-relay-log.index

expire_logs_days        = 10
max_binlog_size         = 500M

Danach starten wir MySQL auf dem Server neu:

/etc/init.d/mysql restart

und richten die Replikation ein hier werden die Werte von dem Masterserver verwendet

mysql -u root -p

CHANGE MASTER TO MASTER_HOST='IP_MASTER', MASTER_USER='replikation_user', MASTER_PASSWORD='replikation_password', MASTER_LOG_FILE='mysql-bin.000009', MASTER_LOG_POS=113;
START SLAVE;

Den Status der Replikation überprüfen wir mit:

SHOW SLAVE STATUS\G
*************************** 1. row ***************************
             Slave_IO_State: Waiting for master to send event
                Master_Host: IP_MASTER
                Master_User: replikation_user
                Master_Port: 3306
              Connect_Retry: 60
            Master_Log_File: mysql-bin.000009
        Read_Master_Log_Pos: 130
             Relay_Log_File: slave-relay-bin.000001
              Relay_Log_Pos: 00000004
      Relay_Master_Log_File: mysql-bin.000001
           Slave_IO_Running: Yes
          Slave_SQL_Running: Yes
            Replicate_Do_DB:
        Replicate_Ignore_DB:
         Replicate_Do_Table:
     Replicate_Ignore_Table:
    Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
                 Last_Errno: 0
                 Last_Error:
               Skip_Counter: 0
        Exec_Master_Log_Pos: 2
            Relay_Log_Space: 690471192
            Until_Condition: None
             Until_Log_File:
              Until_Log_Pos: 0
         Master_SSL_Allowed: No
         Master_SSL_CA_File:
         Master_SSL_CA_Path:
            Master_SSL_Cert:
          Master_SSL_Cipher:
             Master_SSL_Key:
      Seconds_Behind_Master: NULL
1 row in set (0.00 sec)

Wichtig: Slave_IO_Running und Slave_SQL_Running müssen auf Yes stehen. Anderen Falles stimmen z.B. die Userberechtigungen des Replikationsusers nicht, das Passwort ist nicht oder nicht richtig eingetragen, oder  die MySQL Instanz kann sich nicht zum Master verbinden(Port, Ip usw.). Wie solche DInge repariert werden folgt an anderer Stelle.

Wenn der Master schon Daten enthält müssen wir anders vorgehen. Hierzu gibt es mehrere Varianten – die von mir vorgestellte benutze ich fast wöchentlich um Replikationen neu Aufzusetzen. Wenn wir den Master und den Slave vorbereitet haben, ziehen wir uns ein Backup mit mysqldump auf dem Masterserver.

Achtung je nachdem welche Engines ihr benutzt und wie diese verwendet werden, kann es zu Problemen führen. Die INNODB – Variante berücksichtigt, dass nur in Innodbtabellen geschrieben wird und somit können wir im Livebetrieb ein konsistentes Backup für eine Replikation ziehen. Wenn Ihr auch MyISAM Tabellen im Einsatz habt und in diese auch geschrieben wird, muss die Datenbank erst gelocked werden, siehe weiter unten.

INNODB

mysqldump -uroot -p --triggers --routines --verbose --master-data=2 --flush-logs --single-transaction --all-databases | gzip -1 -c > /pfad/dump.sql.gz

MyISAM

mysql -uroot -p

FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000999 |      112 |              |                  |
+------------------+----------+--------------+------------------+

Damit haben wir den Master gelocked, sprich es können keine Daten in die Datenbank geschrieben werden.

mysqldump -u root -p --triggers --routines --verbose --all-databases | gzip -1 -c > /pfad/dump.sql.gz

Nachdem wir nun den Dump auf den Slave kopiert haben spielen wir ihn in die Datenbank ein:

gunzip -c /pfad/dump.sql.gz | mysql -uroot -p

INNODB

gunzip -c /pfad/dump.sql.gz | head -n22 | tail -n1
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.122978', MASTER_LOG_POS=98;

mysql -uroot -p

CHANGE MASTER TO MASTER_HOST='IP_MASTER', MASTER_USER='replikation_user', MASTER_PASSWORD='replikation_password', MASTER_LOG_FILE='mysql-bin.122978', MASTER_LOG_POS=98;
START SLAVE;

MyISAM

Hier benutzen wir die Angaben aus dem SHOW MASTER Befehl des gelockten Masters.

mysql -uroot -p

CHANGE MASTER TO MASTER_HOST='IP_MASTER', MASTER_USER='replikation_user', MASTER_PASSWORD='replikation_password', MASTER_LOG_FILE='mysql-bin..000999', MASTER_LOG_POS=112;
START SLAVE;

Wenn wir überprüft haben, dass die Replikation läuft (SHOW SLAVE STATUS;) müssen wir in der MyISAM – Variante nur noch die Datenbanken auf dem Master wieder freigeben:

 UNLOCK TABLES;
  • Dez
  • 28
  • 2009

Tuning TCP Linux

Posted by okami In Featured, Howtos | No Comments »

Das Tutorial basiert auf dem TCP Tuning Linux Guide & TCP Tuning for WAN und ist im wesentlichen eine Übersetzung mit ein paar zusätzlichen Erläuterungen

LINUX

Da es  unterschiedliche TCP Optionen in denKernelversionen 2.4. und 2.6. gibt, soll es uns im folgenden ausschliesslich um Kernelversionen der 2.6 – Familie gehen. Prinzipiell finden sich alle Parameter in der Datei ip-sysctl.txt die den Kernelsourcen beiligt. Um die TCP Einstellungen zu ändern, werden die Einträge entweder in die /etc/sysctl.conf eingefügt oder entsprechend abgeändert und mit “sysctl -p” übernommen.

Als erstes erhöhen wir  den zu klein geratenen TCP buffer:

net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_moderate_rcvbuf = 1
sysctl net.ipv4.tcp_sack =  0

# für Gigabitadapter
net.core.netdev_max_backlog = 2500
#für 10 Gigabit
net.core.netdev_max_backlog = 30000

Darüber hinaus überprüfen wir ob folgende Werte auf 1 gesetzt sind:

sysctl net.ipv4.tcp_window_scaling
sysctl net.ipv4.tcp_timestamps

Mit der Kernelversion 2.6.13 unterstützt Linux sogenannte “pluggable congestion control algorithmen” . Welche Algorithmus Verwendung finden soll, wird mittels net.ipv4.tcp_congestion_control festgelegt. Abhängig von der Kernelversion sollte er default auf cubic oder reno stehen. Um nachzuschauen welche Algorithmen der Kernel unterstützt:

sysctl net.ipv4.tcp_available_congestion_control

Von Hause aus stehen mehrere Algorithmen zur Verfügung, die Unterstützung muss beim kompilieren des Kernel berücksichtigt werden. Weiterführende Informationen und Arbeitsweise der einzelnen Algorithmen findet sich hier. Ein Benchmark über die unterschiedlichen Algorithmen mit diversen MTU Werten findet sich hier für eine Teststellung im 10GBit Bereich. Der Algorithmus wird dann beispielsweise durch

sysctl -w net.ipv4.tcp_congestion_control=htcp

gesetzt.

Um den Durchsatz zu erhöhen können wir ebenso die die Queue des Interfaces anpassen:

ifconfig eth0 txqueuelen 10000

Letzteres ist einzig für Gigabit Ethernet Adapter zu empfehlen, darüber hinaus ist an dieser Stelle mit Nebenwirkungen zu rechnen: wie z.B. dass die einzelnen Streams nicht mehr gleichwertig das Medieum teilen.

Jumbo Frames und die Spielerei mit den MTU-Werten:

Laut IEEE 802.3 haben Frames im Ethernet eine maximale Größe von 1518 Byte. Das ergibt beim Einsatz von IP eine MTU Größe von 1500 Byte. Als Jumbo Frames werden nun  Frames mit einer Größe über 1518 Byte bezeichnet. Jumbo Frames sind ersteinmal nicht standardisiert. Jeder Netzwerkhersteller implementiert hier seinen eigenen “Standard”. Typischweise werden Framegrößen von 9 kB, 12kB, 14 kB und 16 kB verwendet. Der Einsatz von Jumbo Frames soll die Interruptlast der beteiligten Stationen verringern. Ein weiterer positiver Effekt, der großen Frames, ist der kleinere Protokolloverhead.

Damit die Übertragung von Jumbo Frames funktioniert, müssen alle Switche und Router zwischen Sender und Empfänger diese unterstützen. Und hier fangen die Probleme an. Da kein Standard existiert, ist die Unterstützung der Hersteller recht unterschiedlich. Auch zwischen den einzelnen Produkten eines Herstellers gibt es oft Unterschiede bei der Behandlung von “Jumbos”. Cisco unterstützt Jumbo Frames nur bei bestimmten Modulen und teilweise nur auf bestimmten Ports von Modulen. Hier ist also Lesen angesagt. Sinnvoll ist der Einsatz von Jumbo Frames unter Umständen in einem Cluster Server, da hier die Member des Clusters über eine kontrollierte Infrastruktur kommunizieren. Switche, Router und Netzwerkkarten die keine großen Frames kennen, verwerfen die Jumbos einfach. In den Fehlercountern tauchen diese dann als Giants auf.

Kategorien