Gestern Abend habe ich beim Berliner WordPress-Meetup einen Vortrag zum Thema Serialisierte Daten in der WP-Datenbank und die Konsequenzen für einen Datenbank-Umzug zu einer anderen Domain gehalten. Dies ist nun der angekündigte Artikel zu diesem Thema.

Ich will zunächst beschreiben, wie ich zu diesem Thema kam. Es hört sich ein wenig kompliziert an, ist es aber, wenn man den Kern des Problems begriffen hat, nicht mehr. Außerdem gibt es sehr einfache und gangbare Lösungen.

WordPress auf eine andere Domain umziehen – Probleme und Lösungen

Sehr viele, die mit WordPress arbeiten, werden früher oder später mindestens einmal mit diesem Problem konfrontiert. Wo sucht man Hilfe? Richtig, bei Tante Google! Das habe ich bei meinem ersten Umzug getan und gestern Nachmittag zu Recherchezwecken noch einmal:

'wordpress domain umziehen' – Google-Suche

'wordpress domain umziehen' – Google-Suchergebnis

Ergebnis der Google-Suche: ‚wordpress domain umziehen‘

Die Suche ergab gestern ungefähr 33.800 Treffer. Die ersten sechs davon habe ich mir etwas näher angesehen. Und was soll ich sagen? Ich war einigermaßen entsetzt! Mit dem Google Content Quality Score (vgl. Andreas Graap) scheint es nicht allzu weit her zu sein: Unter den ersten sechs Treffern wird viermal eine unvollständige Lösung präsentiert, die im Einzelfall zu erheblichen Problemen führen kann!

Als den Gipfel der Unverschämtheit empfinde ich Treffer Nr. 5, eine FAQ-Seite von WordPress Deutschland, einer von der Fa. Inpsyde GmbH betriebenen Seite. Inpsyde selbst behauptet auf ihrer Website mit großen Lettern: „WordPress können wir. Und zwar so richtig, richtig gut.“ Diese FAQ-Seite auf wpde.org macht allerdings nicht diesen Eindruck.

Wie bei drei anderen unter den ersten Treffern wird das Thema Serialisierte Daten (Serialized Data) komplett verschwiegen. Stattdessen wird meistens der (unvollständige) Weg beschrieben, den auch ich einige Jahre beschritten habe.

Zunächst aber seien hier noch die beiden Artikel genannt, die das Problem in seiner Gänze benennen und eine Lösung dafür anbieten:

21 ist nur die halbe Wahrheit

Aber nun Schritt für Schritt. Die Aufgabe ist folgende: Eine komplette WordPress-Installation soll von einer Domain zur anderen umgezogen werden. Als Theme-Entwickler arbeite ich häufig mit einer Testumgebung, die ich auf einer Subdomain einer meiner Domains dem Kunden präsentieren kann. Nach erfolgter Abnahme soll dann die komplette Website auf die Domain des Kunden übertragen werden:

test.mydomain.tld => newdomain.tld

Die „manuelle“ Lösung

Wenn man nicht zu einem PlugIn greift, das diese Aufgabe komplett automatisiert erledigt, gliedert sich die Aufgabe im Prinzip in drei Schritte:

  1. Files per FTP transferrieren
  2. Datenbank-Zugangsdaten in der wp_config.php auf der Zieldomain anpassen.
  3. Datenbank migrieren
    Dieser Schritt gliedert sich wiederum in drei Schritte:

    1. Datenbank von alter Domain exportieren
    2. Datenbank bearbeiten
    3. Datenbank auf neuer Domain importieren

    Dazu ist anzumerken, dass diese Reihenfolge so nicht zwingend ist. Schritt b kann auch vor bzw. gleichzeitig mit Schritt a, oder auch erst nach Schritt c erfolgen.

Sehen wir uns Punkt 3.b einmal näher an:

Datenbank bearbeiten

Das Verfahren, das meistens dafür vorgeschlagen wird, ist relativ simpel: An möglichst jeder Stelle in der Datenbank muss mittels Suchen & Ersetzen die alte Domain test.mydomain.tld durch die neue Domain test.mydomain.tld ersetzt werden. Dazu gibt es drei Möglichkeiten:

  • In der Datenbank direkt, z. B. mittels phpMyAdmin oder einem vergleichbaren Tool, durch ein paar SQL-Befehle. Hier ein (angepasstes) Beispiel von WP Beaches:
    UPDATE wp_options SET option_value = replace(option_value, 'test.mydomain.tld', 'newdomain.tld') WHERE option_name = 'home' OR option_name = 'siteurl';
    
    UPDATE wp_posts SET guid = replace(guid, 'test.mydomain.tld','newdomain.tld');
    
    UPDATE wp_posts SET post_content = replace(post_content, 'test.mydomain.tld', 'newdomain.tld');
    
    UPDATE wp_postmeta SET meta_value = replace(meta_value,'test.mydomain.tld','newdomain.tld');

    Oft wird sogar lediglich empfohlen, nur zwei Einträge in der wp_options-Tabelle zu ändern, siteurl und home. Wenn allerdings in der wp_posts– bzw. wp_postmeta-Tabelle keine Änderungen durchgeführt werden, zeigen alle absolut gespeicherten Pfade (WordPress tut das z. B. beim Einfügen von Bildern in Artikel) noch auf die alte Domain.

  • Mit einem Texteditor, in dem man den Datenbank-Dump geöffnet hat.
  • Mittles eines PlugIns. Oft wird hierfür das PlugIn Search and Replace von Frank Bültge empfohlen.

Funktioniert das? Ja, aber …

Die WordPress-Installation wird, wenn man die Domain sowohl in der wp_posts– bzw. wp_postmeta-Tabelle, als auch in der wp_options-Tabelle ersetzt hat, im Großen und Ganzen funktionieren.

Probleme bei Widgets und PlugIns

Wenn Probleme auftreten, dann meist bei Widgets und PlugIns. Woran liegt das? Die Antwort lautet:

Serialisierte Daten (Serialized Data)

Exkurs

Dazu zunächst ein kleiner Exkurs:

Meetup-Kollege Bernhard Kau hat einen hervorragenden Artikel darüber geschrieben, welche Möglichkeiten es gibt, Arrays und ähnliche Datengebild in einer Datenbank zu speichern. Darin zeigt er 4 Möglichkeiten auf:

  1. Der schlechte Weg
  2. PHP serialize()
  3. JSON (JavaScript Object Notation)
  4. „light“ – PHP explode() / implode()

Ich möchte hier nur auf die ersten beiden Wege eingehen.

Der „schlechte“ Weg

Da dieses, mein WordPress Blog bereits seit 2007 existiert, ist die wp_options-Tabelle in der Datenbank ein riesiger Datenfriedhof, der viele Relikte aus längst vergangenen Tagen beherbergt. Ein Beispiel für den „schlechten“ Weg, ein Array in der WP-Datenbank zu speichern, ist das PlugIn Audio Player, welches vor der WordPress-Version 3.6 notwendig war, um Audiofiles abspielen zu können. In einer frühen Version speicherte das PlugIn seine Einstellungen so in der wp_options-Tabelle ab:

Array in MySQL-Datenbank speichern: Der schlechte Weg

Für jedes Schlüssel-Wert-Paar wird hier eine eigene Tabellenzeile, insgesamt also 20 Zeilen, verbraucht.

PHP serialize()

In einer späteren Version des oben erwähnten PlugIns wird dann der Weg mittels PHP serialize() beschritten. Das Ergebnis in der Datenbank sieht so aus:

Array in MySQL-Datenbank mittels PHP serialize() gespeichert

Der Verbrauch ist, obwohl das Array inzwischen 21 Schlüssel-Wert-Paare hat, auf 1 Tabellenzeile gesunken.

Wie funktioniert PHP serialize()?

Obiges Beispiel ist zum einfachen Nachvollziehen ein wenig zu umfangreich, deshalb hier ein sehr simples Beispiel, um die Funktionsweise der Serialisierung in PHP zu verstehen. Ausgangspunkt ist in diesem Beispiel ein Array mit lediglich einem Schlüssel-Wert-Paar:

array(
	"url" => "http://test.maydomain.tld"
)

Die Serialisierung liefert folgenden String:

a:1:{s:3:"url";s:25:"http://test.maydomain.tld";}

Wer sich dafür interessiert, wie dieses Format im Einzelnen aufgebaut ist, dem sei eine Übersicht bei stackoverflow.com empfohlen: Structure of a Serialized PHP string

Für unsere Betrachtung ist ausreichend zu wissen, dass a für Array steht und s für String. Die Zahl unmittelbar nach s: ist die Stringlänge. Und hier zeigt sich der Grund für die Probleme bei der Datenbank-Migration nach der oben beschriebenen Methode: Durch bloßes Suchen und Ersetzen der URLs werden die Stringlängen nicht mit ersetzt. Wenn PlugIns bzw. Widgets diese fehlerhaften Informationen aus der wp_options-Tabelle laden, kommt es zu einem verhängnisvollen Fehler, der dazu führt, dass die Inhalte bzw. Einstellungen komplett verschwunden sind.

Lösungen für die vollständige Datenbank-Migration

Um das Problem mit den serialisierten Daten zu lösen, gibt es mehrere Möglichkeiten. Oft genannt wird das Database Search and Replace Script in PHP von interconnct/it. Noch bequemer geht es allerdings mit einem PlugIn:

PlugIn-Empfehlung: WP Migrate DB

Es gibt einige PlugIns, die mit serialisierten Daten umgehen können. Mein Favorit darunter ist WP Migrate DB. Auf der Ursprungsdomain installiert man dieses PlugIn, gibt die zu verändernden Daten ein und kann dann die fertig bearbeitete Datenbank downloaden. Bereits in der kostenlosen Version kann man Profile für wiederkehrende Migrationen speichern. Außerdem kommt auch bereits die kostenlose Version sehr gut mit Multisite-Installationen zurecht.

Screenshot WP Migrate DB

Screenshot WP Migrate DB

Im oben bereits erwähnten Artikel auf Blogs54 gibt es eine ausführliche Beschreibung zu WP Migrate DB.

All-In-One-Lösungen

Wer nicht die oben beschriebene Lösung „von Hand“ benutzen, sondern Files und Datenbank gemeinsam umziehen will, dem seien hier noch der Vollständigkeit halber drei All-In-One-Lösungen empfohlen:

Keine der drei Lösungen habe ich selbst getestet. Bei meinen Recherchen bin ich aber zu der Erkenntnis gekommen, das wohl auch diese Lösungen mit serialisierten Daten zurecht kommen.

Fazit

Ein Umzug einer WordPress-Installation auf eine andere Domain ist nicht schwierig und gelingt auch problemlos, wenn man weiß wie. Leider wird das Problem mit den serialisierten Daten in vielen Anleitungen im Netz oft unterschlagen, was zu Problemen führen kann. In diesem Artikel habe ich Lösungen gezeigt, wie man diese Probleme vermeiden kann.

Frage an meine Leser: Was ist Eure bevorzugte Methode bei der WordPress-Migration?

» Folien zum Vortrag „Serialized Data“ beim WP-Meetup Berlin am 30.04.2015