Migration dreier CEs in eine EE-OXID-Instanz

Warum drei? Im Prinzip egal. Wichtig ist mir der Aspekt: mehr als eins!

Es gibt eine Menge Features, die in eine OXID-Installation mit einem Upgrade auf eine EE-Umgebung Einzug halten. Diese Feature sind aber für dieses Thema unrelevant. Wichtig ist hier der Fokus auf die Datenbank und auf die Features die datenbanktechnisch den Unterschied zwischen einer CE und EE machen (Stichwort: Multishop und Vererbung).

Vor der Migration müssen alle Versionen der betroffenen Systeme auf einen Versions-Stand gebracht werden. Es empfhielt sich die Release-Seite von OXID zu konsultieren (Beispielhaft OXID v6.2.3).

Darum der erste Blick auf die Datenbank einer frischen EE-Installation mit drei Dummy-Sub-Shops, bereits gefüllt mit ein paar Artikeln und Kategorien.

Vorbetrachung der neuen EE-DB

Feld „oxshopid“

Bereits in der CE gibt es in fast allen Tabellen das Feld oxshopid. Das war dort insofern uninteressant, da eine CE-Instanz genaum einem Shop entsprach. Das Feld ist daher standardmäßig immer mit 1 gefüllt ist.

In der EE ist das Feld erwartungsgemäß auch mit „2“ und „3“ befüllt. Das sind dann bereits Daten, die explizit einem bestimmten Sub-Shop zugeordnet sind.

Tabelle „oxshops“

Beim Thema Sub-Shop lohnt sich jetzt der Blick auf die Tabelle oxshops. Hier gibt es einige neue Felder die unter anderem die Vererbung steuern.

Tabellen „…2shops“

Es gibt einige neue Tabellen die auf …2shops enden. Die Tabellen die das betrifft findet man im EE-Backend unter Stammdaten > Grundeinstellungen > Mall > Vererbung vom Elternshop. Warum es diese Tabellen zusätzlich zur Idee des Feldes oxshopid gibt, ist schnell erklärt. Wenn nur die oxshopid zum Einsatz käme, dann könnte ich Artikel nur für jeden Sub-Shop separat darstellen. Es würde zu Datenbank-Dubletten kommen. Durch die Vererbung kann ich jetzt aber z.B. Artikel nur im Mastershop pflegen und vererbe sie einfach in die Sub-Shops.

An dieser Stelle sind also auch Überlegungen zu treffen, ob die eigenen Module mit eigenen Datenbanken mindestens die oxshopid haben und ob es nicht sogar sinnvoll ist eine Vererbung anzubieten, sprich dafür dann auch eigene …2shops Tabellen anzulegen (Welche Konsequenzen das für die Modulentwicklung hat, weiter unten).

Neue Views

Was auch sofort ins Auge fällt, sind die neuen Views. Von der CE sind die Root-View (z.B. oxv_oxarticles) und – je nachdem wie viele Sprachen man aktiviert hat – die Sprachviews (z.B. oxv_oxarticles_de, oxv_oxarticles_en) bekannt. In der EE kommen jetzt zu jedem Sub-Shop weitere Views hinzu (z.B. oxv_oxarticles_1, oxv_oxarticles_1_de, oxv_oxarticles_1_en – Die Ziffer gilt für die Sub-Shop-Id).

Vorbetrachung der „alten“ CE-DB

alte Inhalte

Bei der Übernahmen der Inhalte aus den alten Shops können Probleme auftreten, wenn oxids shopübergreifend in den Datensätzen identisch sind. Ein Beispiel sind die OXID-Standard-CMS-Texte wie AGB, Widerruf etc. Die IDs dieser Texte sind in der Regel in allen CE-Instanzen gleich. Auf die muss bei der Migration besonders geachtet werden, damit Inhalte nicht überschrieben werden, sondern für jeden Sub-Shop erhalten bleiben. Möglicherweise gibt es durch gemeinsam genutzte Module ähnliche Konstellantionen.

Konfigurationen (Shop, Module, Themes)

Die Konfigurationen sind schon fast ein Spezialthema. Ich empfehle die Konfigurationen aus dieser Datenbank-Migration herauszuhalten und extra zu betrachten. Es bietet sich hier an einen Config-Im- und Exporters der kompatibel zur CE und EE Version zu nutzen. Bei dem Vorgang ist es besonders wichtig, das die Versionen der CE und EE identisch sind, da die Im- und Export-Tools meistens für eine Versions-Ebene konzipiert worden sind. Dieses Tool soll den Im- und Export der Shop-, Modul- und Theme-Konfigurationen unterstützen. Der Ansatz ist, drei CE-Exporte zu erstellen und anschließend damit drei EE-Sub-Shop-Importe durchzuführen.

Zwischenüberlegungen zur Migration

vererben vs. Jeder Sub-Shop individuell

Beim betrachten der neuen Daten-Struktur ist spätestens jetzt der Zeitpunkt zu überlegen, was mit den Daten aus den drei CEs werden soll (in der Regel legt das der Auftraggeber fest). Wenn jeder Sub-Shop seine eigenen Daten behalten soll und keine Vererbung stattfindet, muss man bei der Migration prinzipiell „nur“ dafür sorgen, das die oxshopids korrekt getauscht werden. Wenn aber vererbt werden soll, dann gilt es genau zu überlegen, was vererbt werden soll. Nur die Artikel? Oder nur die News? Kommt es zur Vererbung, bleibt die oxshopid in der Regel die „1“ und durch die zusätzliche Befüllung der …2shops-Tabellen erfolgt dann die Zuordnung in die Sub-Shops.

Erweiterungen durch Module

Wichtig ist, dass in der EE-Instanz sämtliche Module aller CEs gleichzeitig in den Sub-Shops zu sehen sein werden und ggf. einfach nicht aktiviert sind. Das bedeutet im Umkehrschluss, das die Datenbank-Struktur aus einer CE dann bei allen Sub-Shops vorhanden, aber nicht gefüllt sein muss.

Migrationstechniken

Von der Schnelligkeit sind mysqldumps und Konsolen-basierte SQL-Importe der ideale Weg. Da drei unterschiedliche CE-Strukturen in eine nochmals abweichende EE-Struktur vorgenommen werden, gilt es Daten-SQLs und Struktur-SQLs voneinander zu trennen. Generell muss die Struktur je Importschritt mit angepasst werden.

In bestimmten Fällen ist es zudem besser die Schritte nicht nur via Konsolen-SQLs durchzuführen, sondern mit kleinen Scripten die Anpassungen der DB durch die Infrastruktur von OXID erfolgen zu lassen.

DB-Migrationsstrategie

Aus den Zwischenüberlegungen ergibt sich folgende Strategie:

Export CE

  • Bereitstellung einer leeren CE-Instanz und einer leeren EE-Instanz
  • Erstellung der drei CE-DB-Dumps via mysqldump, ohne Drop-Table

Vorbehandlung der CE-Dumps für die Zusammenführung

  • Import des ersten CE-Dumps in die leere CE-Instanz
  • Hier die Views löschen
  • ggf. hier schon Daten aufräumen die mglw. in der EE nicht mehr gebraucht werden (alte DB-Leichen, nicht mehr genutzte Tabellen, Spalten …)
  • Anpassung der CE-Instanz (shopids, content-oxids, seo-oxids, indizes – weiter unten dazu mehr)
  • Export der CE-Instanz
  • CE-Instanz leeren (Daten und Tabellen)

Diesen Block für alle drei CE-Shops wiederholen

Gemeinsamer CE-Import & Export

  • Alle drei CE-Instanz-Exporte jetzt hintereinander in die nachmals vollständig geleerte CE-Instanz importieren
  • Bei jedem Zwischen-Import empfehle ich die DB-Struktur in einem „Begleit-SQL-Script“ so anzupassen, dass die Daten ohne „Drop-Table“ importiert werden können (Es gibt leider in MySQL kein Befehl „Vergleiche die vorhandene Datenstrukur mit folgender und passe nur die Änderungen an“).
  • Export der nun kompletten CE-Instanz

Import in EE

  • Import des CE-Exports in die EE-Instanz
  • Multishop-Mapping anstoßen
  • Views erzeugen

Migration

Im Einzelnen hier nun konkrete toDos:

Konfigruationen aus den CEs exportieren und in die EE importieren (Überlegungen, siehe oben).

Parallel zur DB ist die Synchronisation der Bilder und Medien aus allen drei Shops zu organisieren. Da das ein nicht unerheblicher Zeitaufwand ist, lohnt es sich auch hier Shell- oder Konsolen-Scripte zu schreiben die direkt die Dateien aus den CE-Instanzen in die eine EE-Instanz synchronisieren. Eventuell könnte man sich bei den Produktbildern nur auf die Master-Bilder konzentrieren und die dynamischen Bilder später dann sukessive durch den Shop wieder aufbauen lassen. Das würde jetzt Migrationszeit ersparen, aber den Shop in der Anfangsphase nach der Umstellung möglicherweise mehr belasten. Hier also abwägen.

Bei der DB-Migration hier noch einige vertiefende Tipps zur oben genannten Migrations-Strategie:

Anpassung der CE-Instanzen

oxshopid

Beim zweiten und dritten CE-Shop muss die oxshopid von „1“ auf „2“ bzw. „3“ umgestellt werden. Das gelingt am Besten mit einem Script, das ein Update-SQL baut. Das Update-SQL kann anschließend via Konsole eingespielt werden. Das folgende MySQL-Script am Besten mit OXID aufrufen, das Ergebnis dann iterieren. Wichtig ist, das bei den Dateb die später vererbt werden sollen (z.B. Artikel) die Umstellung der oxshopid nicht erfolgen darf. Das wird dann über die Vererbungs-Funktion von OXID gelöst.

select table_name, column_name
from information_schema.COLUMNS
where column_name LIKE '%SHOPID'
and table_schema like '_____DBNAME____'
and table_name not like 'oxv_%'

indizes

In der oxcontent muss der Index angepasst werden, da die oxloadid mehrmals (je sub-shop) verwendet werden kann:

ALTER TABLE oxcontents ADD UNIQUE OXLOADID (OXLOADID, OXSHOPID),
DROP INDEX OXLOADID;

content-oxids, seo-oxids

Für die content-oxids muss jetzt noch eine Umstellung in zwei Tabellen erfolgen. Auch hier bietet sich die Arbeit mit einem OXID-PHP-Script an. Zuerst alle IDs holen:

SELECT `oxid`, `oxloadid` from oxcontents

Anschließend wird aus der neuen oxshopid und der oxloadid eine neue oxid via md5 erzeugt. Damit dann die Updates:

<?php

setContentId(
    $data['oxid'],
    md5($data['oxloadid'] . $newShopId)
);

setSeoContentId(
    $data['oxid'],
    md5($data['oxloadid'] . $newShopId)
);


function setContentId($sOxId, $sNewOxId)
{
    echo $sUpdate = "update `oxcontent` set `oxid` = '{$sNewOxId}' where `oxid` = '{$sOxId}';\n";
}

function setSeoContentId($sOxId, $sNewOxId)
{
    echo $sUpdate = "update `oxseo` set `oxobjectid`='{$sNewOxId}', `oxstdurl`=replace(`oxstdurl`, '{$sOxId}', '{$sNewOxId}') where oxobjectid='{$sOxId}';\n";
}

Multishop-Mapping

Beim Multishop-Mapping gilt es wieder die vorher definierten Vererbungsregeln zu beachten. Welche Tabellen „Multishop“-fähig sind, steht in den Variable aMultiShopTables. Bei den Tabellen die mit Vererbung arbeiten sollen müssen alle Shops durchlaufen werden. Bei den anderen reicht der Bezug zum Sub-Shop selbst. Im folgenden Beispiel wird die Vererbung nur bei den Artikeln und Attributen angewendet. Alle anderen Inhalte bleiben dem jeweiligen Sub-Shop vorbehalten:

<?php
    $oConfig = Registry::getConfig();
    $aMultiShopTables = $oConfig->getShopConfVar('aMultiShopTables');
    foreach ($aMultiShopTables as $sMultiShopTable) {
        if (in_array($sMultiShopTable, ['oxarticles', 'oxattribute'])) {
            foreach($oConfig->getShopIds() as $iShopId) {
                echo $sInsert = "INSERT IGNORE INTO `{$sMultiShopTable}2shop` (`oxshopid`, `oxmapobjectid`)
                    SELECT '{$iShopId}' as oxshopid, `oxmapid`
                    FROM `{$sMultiShopTable}`;\n";
            }
        }
        else {
            echo $sInsert = "INSERT IGNORE INTO `{$sMultiShopTable}2shop` (`oxshopid`, `oxmapobjectid`)
                SELECT `oxshopid`, `oxmapid`
                FROM `{$sMultiShopTable}`;\n";
        }
    }

Fazit

Die Vorbereitung der Migration und die Testläufe nehmen sicher einiges an Zeit ein. Ist aber alles gut vorbereitet, ist ein vollständiger Migrationslauf in gut 1-2 Stunden durchgeführt.