Exe­cu­ti­ve Summary:

Bei par­al­le­lem Betrieb von Ent­wick­lungs- und Live-Sys­te­men in Woo­Com­mer­ce ent­ste­hen zwei unter­schied­li­che Daten­stän­de: ein tech­nisch opti­mier­ter Dev-Stand und ein fort­lau­fend wach­sen­der Live-Stand mit neu­en Bestellungen.
Ein siche­rer Go-Live erfor­dert daher kei­nen Kom­plett-Over­wri­te, son­dern einen kol­li­si­ons­frei­en Del­ta-Abgleich, bei dem aus­schließ­lich neue Daten seit einem Stich­tag über­nom­men wer­den, wäh­rend tech­ni­sche Opti­mie­run­gen erhal­ten bleiben.

Jeder will ein Stück vom KI Kuchen
Reddit Reddit

Wenn zwei Sys­te­me par­al­lel arbeiten:

Häu­fig haben wir als Word­Press Agen­tur die Auf­ga­be, bestehen­de Word­Press Sys­te­me zu über­ar­bei­ten. Ent­we­der im Rah­men einer tech­ni­schen Über­ar­bei­tung (z. B. Lade­zeit­op­ti­mie­rung) oder bei der Zusam­men­le­gung von zwei Web­sites zu einem har­mo­ni­schen Gesamtsystem.

Wenn man ver­schie­de­ne Word­Press Sys­te­me zusam­men­führt, dann kommt es beim Ein­satz eines Woo­Com­mer­ce Sys­tem häu­fig dazu, dass die tech­ni­schen Arbei­ten par­al­lel zum lau­fen­den Betrieb des exis­tie­ren­den Online­shops durch­führt. Die Arbei­ten wer­den natür­lich im Hin­ter­grund auf einem vor Such­ma­schi­nen abge­schirm­ten Schat­ten­ser­ver durch­ge­führt. Dabei wird der aktu­el­le Stand des bestehen­den Sys­tems zum Zeit­punkt der Kopie “ein­ge­fro­ren”.

Reddit Reddit

Arbeits-Sys­tem (Dev-Ser­ver*):

Die höchs­te Bestell­num­mer sei im Bei­spiel die Num­mer 20.465. Die­se ist und bleibt im kopier­ten Arbeits­sys­tem auch bestehen. Nor­mal ändert sich die Anzahl der Bestel­lun­gen (Bestell-IDs) nicht. Eben­so ändern sich auch die Anzah­len der Sei­ten (Sei­ten-IDs), oder die Anzah­len der Blog­ein­trä­ge (Blog-IDs) nicht. Die­se wer­den jeweils nur dann +1 hoch­ge­zählt, wenn man zu Test-Zwe­cken eine Test­be­stel­lung aus­führt. Neh­men wir an, im Zuge der Arbei­ten wer­den noch vier Test-Bestel­lun­gen aus­ge­führt, um die opti­mier­te Funk­ti­ons­wei­se zu tes­ten. Die höchs­te Bestell­num­mer wird am Ende also die 20.465 + 4 also Bestell-ID 20.469 sein.

* Dev-Ser­ver steht für “Deve­lo­p­ment-Ser­ver”, also den Ent­wick­lungs-Ser­ver, auf dem die Arbei­ten durch­ge­führt wer­den (abge­schirmt vor Google, damit es kei­ne dupli­zier­ten Inhal­te in der Such­ma­schi­ne gibt).

Pro­duk­tiv-Sys­tem (Live-Ser­ver):

Anders als am Dev-Ser­ver wird am Live-Ser­ver der Shop natür­lich pro­duk­tiv wei­ter betrie­ben. Bei­trags-IDs für neue Blog­bei­trä­ge, Sei­ten-IDs für neue Inhalts­sei­ten und natür­lich auch Bestell-IDs für neue Bestel­lun­gen wer­den mun­ter wei­ter hoch­ge­zählt. Der Rubel muss rol­len, daher lässt man den Shop typi­scher­wei­se nor­mal wei­ter lau­fen, ohne den Shop in einen War­tungs­mo­dus zu ver­set­zen — dann könn­ten näm­lich kei­ne Bestel­lun­gen mehr angeom­men wer­den. Der Zäh­ler für die ein­deu­ti­gen IDs wird daher mit jeder neu­en Bestel­lung und jedem Arbei­ten an der Web­site beim Spei­chern eines Zwi­schen­stan­des inkrementiert.

Neh­men wir also im Bei­spiel an, dass eini­ge Blog­ar­ti­kel ver­öf­fent­licht wer­den, Sei­ten­über­ar­bei­tun­gen erfol­gen und diver­se Bestel­lun­gen ein­ge­hen, dann kann die neu­es­te Bestell-ID gut und ger­ne +200 Num­mern wei­ter sein, also bei 20.465 + 200, also Bestell-ID 20.665 liegen.

Reddit Reddit

Zusam­men­füh­ren der bei­den Welten:

Nach­dem die Arbei­ten am Dev-Ser­ver abge­schlos­sen sind, soll der tech­nisch neue und über­ar­bei­te­te Stand auf den Live-Ser­ver über­führt wer­den. Dabei ist es wich­tig, dass die neu ein­ge­gan­ge­nen Bestel­lun­gen seit dem Zeit­punkt des Erstel­lens der Arbeits­ko­pie nicht ver­lo­ren gehen. Eine Zusam­men­füh­rung unter Bei­be­hal­tung der Bestel­lun­gen ist das Ziel. Ein­ge­gan­ge­ne Bestel­lun­gen, stor­nier­te Bestel­lun­gen, Retou­ren, genutz­te Rabatt­codes, Affi­lia­te-Bestel­lun­gen, tele­fo­nisch plat­zier­te Orders oder auch Wie­der­käu­fe dür­fen nicht ver­lo­ren gehen. Die Zusam­men­füh­rung muss daher tech­nisch sau­ber und kon­trol­liert erfolgen.

Wir tei­len unser Wis­sen und zei­gen daher die wich­tigs­ten Schrit­te für eine Migra­ti­on von Woo­Com­mer­ce zwi­schen Dev-Ser­ver und Live-Server.

Falsch wäre: Über­spie­len Dev-Ser­ver → Live-Server:

Bei einem ein­fa­chen Über­spie­len des Dev-Ser­vers auf den Live-Ser­ver ist klar, dass die zwi­schen­zeit­lich ein­ge­gan­ge­nen Bestel­lun­gen ver­lo­ren gehen wür­den. Die neu­es­te ID wäre in die­sem Fall die Num­mer 20.469, sodass die letz­ten 200 Ände­run­gen ent­fal­len würden.

Falsch wäre eben­so: Ein­fa­ches Über­spie­len Live-Ser­ver → Dev-Server:

Bei Über­spie­len des Live-Ser­vers auf den Dev-Ser­ver wür­de man natür­lich jeg­li­che Ände­run­gen, das tech­ni­sche Upgrade oder die Opti­mie­run­gen am Dev-Ser­ver wie­der hin­fäl­lig machen. Zwar wären dann die Bestel­lun­gen auf dem Stand, doch alle tech­ni­schen Anpas­sun­gen wären dahin. Auch dies ist kein funk­ti­ons­fä­hi­ger Weg.

Ein­zig rich­ti­ger Weg: Del­ta-Abgleich vom Live-Ser­ver → Dev-Ser­ver → dann kom­plett zum Live-Server:

Puh, die­se Über­schrift hat’s in sich! Wir benö­ti­gen also sowohl die aktu­el­len Bestel­lun­gen und Ände­run­gen, wel­che seit dem Erstel­len der Arbeits­ko­pie (=Stich­da­tum) ange­fal­len sind. Dies kön­nen wir über die Daten­bank erfah­ren. Es gibt das Stich­da­tum, ab dem wir also neue Daten­bank­in­hal­te bezie­hen wollen.

Zugleich wol­len wir die tech­nisch opti­mier­te Ver­si­on des Dev-Ser­vers bei­be­hal­ten. Der ers­te Schritt ist also ein Del­ta-Abgleich aus der Daten­bank des Live-Ser­vers zum Dev-Ser­ver. Dabei kann es aller­dings zu Pro­ble­men kom­men, denn wenn wir das Del­ta direkt ein­spie­len wür­den, wür­de es zu ID-Kon­flik­ten kom­men. Ein gro­ßes Pro­blem wären also Kol­li­sio­nen im ID-Bereich. Daher ist ein „1:1‑Import mit fes­ten IDs“ ris­kant bzw. schlägt spä­tes­tens beim Abgleichz zwi­schen Live-wp_posts.ID zu Dev-wp_posts.ID fehl. Somit ist das Hoch­zäh­len der Post-IDs grund­sätz­lich rich­tig. Doch bit­te nicht per Suchen/Ersetzen in den Daten­bank-Dumps, weil man dabei sehr leicht Zah­len inner­halb von meta_value (Seria­li­sie­run­gen, Tex­te, JSON) kaputt macht.

Die kol­li­si­ons­si­che­re, sau­be­re Lösung ist:

Import in tem­po­rä­re Tabel­len und dann per SQL mit Off­sets in die ech­ten Tabel­len kopie­ren. So wer­den nur die ID-Spal­ten arith­me­tisch ver­scho­ben, ohne meta_value anzu­fas­sen. Dies umgeht mög­li­che ID-Kon­flik­te. Damit wir die Lösung nicht nur ankün­di­gen, son­dern auch lie­fern, fol­gen nun die not­wen­di­gen Daten­bank-Snip­pets. Es wird ange­nom­men, dass fol­gen­de vier Daten­bank-State­ments aus­ge­führt wur­den, um die Daten ab dem Stich­tag zu sichern.

Wich­ti­ger Hin­weis: Arbei­ten Sie nie­mals in der Daten­bank, wenn Sie sich damit nicht aus­ken­nen. Bit­te fer­ti­gen Sie immer voll­stän­di­ge Siche­run­gen an, damit Sie im Fall eines tech­ni­schen Pro­blems zurück­stel­len können.

Reddit Reddit

SQL-State­ment 1:


SELECT *
FROM wp_posts
WHERE post_type = 'shop_order'
  AND post_date > '2025-12-05 11:55:15';

SQL-State­ment 2:


SELECT pm.*
FROM wp_postmeta pm
JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.post_type = 'shop_order'
  AND p.post_date > '2025-12-05 11:55:15';

SQL-State­ment 3:


SELECT oi.*
FROM wp_woocommerce_order_items oi
JOIN wp_posts p ON p.ID = oi.order_id
WHERE p.post_type = 'shop_order'
  AND p.post_date > '2025-12-05 11:55:15';

SQL-State­ment 4:


SELECT oim.*
FROM wp_woocommerce_order_itemmeta oim
JOIN wp_woocommerce_order_items oi ON oi.order_item_id = oim.order_item_id
JOIN wp_posts p ON p.ID = oi.order_id
WHERE p.post_type = 'shop_order'
  AND p.post_date > '2025-12-05 11:55:15';

Del­ta-Abgleich: Live ein­ge­gan­ge­ne Bestel­lun­gen in tem­po­rä­re Tabel­le schreiben:

Die Ziel-Tabel­le hat in. unse­rem Bei­spiel ein ande­res Prä­fix, näm­lich “dss_” statt “wp_”. Bit­te ach­ten Sie daher dar­auf, wel­ches Prä­fix in Ihrer Daten­bank-Instal­la­ti­on ver­wen­det wird. Adap­tie­ren Sie daher bit­te basie­rend auf Ihrem Zielsystem.

Schritt 1: Temp-Tabel­len anle­gen (Struk­tur 1:1 wie Original)


DROP TABLE IF EXISTS dss_tmp_posts;
DROP TABLE IF EXISTS dss_tmp_postmeta;
DROP TABLE IF EXISTS dss_tmp_order_items;
DROP TABLE IF EXISTS dss_tmp_order_itemmeta;

CREATE TABLE dss_tmp_posts LIKE dss_posts;
CREATE TABLE dss_tmp_postmeta LIKE dss_postmeta;
CREATE TABLE dss_tmp_order_items LIKE dss_woocommerce_order_items;
CREATE TABLE dss_tmp_order_itemmeta LIKE dss_woocommerce_order_itemmeta;

Schritt 2: die 4 Dump-Datei­en für den Import anpassen

Wich­tig: kei­ne Zah­len anfas­sen, nur den INSERT INTO … Tabel­len­na­men. In den Datei­en wird jeweils der Ziel-Tabel­len­na­me ange­passt, um eine tem­po­rä­re Tabel­le zu erstellen:
Datei nach SQL-Befehl 1 (posts)
INSERT INTO ‘wp_posts‘ → INSERT INTO ‘dss_tmp_posts‘
Datei nach SQL-Befehl 2 (post­me­ta) — bei uns steht als Shor­te­ner pm
INSERT INTO ‘pm‘ → INSERT INTO ‘dss_tmp_postmeta‘
Datei nach SQL-Befehl 3 (order_items) — bei uns steht als Shor­te­ner oi
INSERT INTO ‘oi‘ → INSERT INTO ‘dss_tmp_order_items‘
Datei nach SQL-Befehl 4 (order_itemmeta) — bei uns steht als Shor­te­ner oim
INSERT INTO ‘oim‘ → INSERT INTO ‘dss_tmp_order_itemmeta‘
Anschlie­ßend impor­tiert man alle vier Datei­en in die Daten­bank des Dev-Sys­tems! Somit erhält man ein tech­nisch sau­be­res und aktu­el­les Word­Press-Kon­strukt, wel­ches zugleich die aktu­ells­ten Bestel­lun­gen ent­hält.

 
 

Typi­scher­wei­se erhält man dann nach dem SQL-Import Erfolgs­mel­dun­gen wie folgt:

15 SQL-Abfragen erfolgreich ausgeführt. (0.019 s)
19 SQL-Abfragen erfolgreich ausgeführt. (0.175 s)
15 SQL-Abfragen erfolgreich ausgeführt. (0.012 s)
15 SQL-Abfragen erfolgreich ausgeführt. (0.036 s)

Schritt 3: Off­sets berech­nen und in ech­te Tabel­le überführen

Die­ser Befehl ist etwas län­ger und daher sau­ber kom­men­tiert. Sie kön­nen die ein­zel­nen Seg­men­te auch nach­ein­an­der aus­füh­ren. Stel­len Sie vor­her sicher, dass die von Ihnen gera­de impor­tier­ten Tabel­len ange­legt wur­den. Bei uns haben die eben das oben genann­te Prä­fix “dss_”, das kann bei Ihnen anders lau­ten. Es ist übri­gens “Best Prac­ti­ce”, nicht “wp_” zu ver­wen­den, wie in jeder Stan­dard­in­stal­la­ti­on. Daher nut­zen wir ein ran­do­mi­sier­tes und spe­zi­fi­zier­tes Daten­bank-Prä­fix in Word­Press und Woo­Com­mer­ce für jede/n unse­rer Kund:innen.


-- Offsets so wählen, dass alles oberhalb der aktuellen Dev-Maxima landet
SET @posts_offset :=
  (SELECT IFNULL(MAX(ID),0) FROM dss_posts) + 1
  - (SELECT MIN(ID) FROM dss_tmp_posts);

SET @pm_offset :=
  (SELECT IFNULL(MAX(meta_id),0) FROM dss_postmeta) + 1
  - (SELECT MIN(meta_id) FROM dss_tmp_postmeta);

SET @oi_offset :=
  (SELECT IFNULL(MAX(order_item_id),0) FROM dss_woocommerce_order_items) + 1
  - (SELECT MIN(order_item_id) FROM dss_tmp_order_items);

SET @oim_offset :=
  (SELECT IFNULL(MAX(meta_id),0) FROM dss_woocommerce_order_itemmeta) + 1
  - (SELECT MIN(meta_id) FROM dss_tmp_order_itemmeta);

-- optional: Offsets anzeigen
SELECT @posts_offset AS posts_offset, @pm_offset AS postmeta_offset,
       @oi_offset AS order_items_offset, @oim_offset AS order_itemmeta_offset;

-- 1) posts (Bestellungen)
-- Wichtig: post_parent bei Refunds/Child-Posts mitverschieben, falls > 0
INSERT INTO dss_posts (
  ID, post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt,
  post_status, comment_status, ping_status, post_password, post_name, to_ping, pinged,
  post_modified, post_modified_gmt, post_content_filtered, post_parent, guid,
  menu_order, post_type, post_mime_type, comment_count
)
SELECT
  ID + @posts_offset,
  post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt,
  post_status, comment_status, ping_status, post_password, post_name, to_ping, pinged,
  post_modified, post_modified_gmt, post_content_filtered,
  CASE WHEN post_parent > 0 THEN post_parent + @posts_offset ELSE 0 END,
  guid,
  menu_order, post_type, post_mime_type, comment_count
FROM dss_tmp_posts;

-- 2) postmeta (Order-Metadaten)
INSERT INTO dss_postmeta (meta_id, post_id, meta_key, meta_value)
SELECT
  meta_id + @pm_offset,
  post_id + @posts_offset,
  meta_key,
  meta_value
FROM dss_tmp_postmeta;

-- 3) order_items (Positionen)
INSERT INTO dss_woocommerce_order_items (order_item_id, order_item_name, order_item_type, order_id)
SELECT
  order_item_id + @oi_offset,
  order_item_name,
  order_item_type,
  order_id + @posts_offset
FROM dss_tmp_order_items;

-- 4) order_itemmeta (Position-Metadaten)
INSERT INTO dss_woocommerce_order_itemmeta (meta_id, order_item_id, meta_key, meta_value)
SELECT
  meta_id + @oim_offset,
  order_item_id + @oi_offset,
  meta_key,
  meta_value
FROM dss_tmp_order_itemmeta;

Auch hier gibt es wie­der Erfolgs­mel­dun­gen, nach jedem Block wie folgt mit einer erstaun­lich kur­zen Ausführungszeit:


Abfrage ausgeführt, 43 Datensätze betroffen. (0.006 s)
Abfrage ausgeführt, 2 115 Datensätze betroffen. (0.184 s)
Abfrage ausgeführt, 87 Datensätze betroffen. (0.001 s)
Abfrage ausgeführt, 832 Datensätze betroffen. (0.020 s)

Schritt 4: Aufräumen

Damit wir die Daten­bank nicht mit unse­ren tem­po­rä­ren Über­bleib­seln des Trans­fers “voll­mül­len”, wol­len wir die­se und die zwi­schen­zeit­lich erzeutg­ten Tran­si­ents eben­so clea­ren. Das geht über den fol­gen­den Befehl:


DROP TABLE IF EXISTS dss_tmp_posts;
DROP TABLE IF EXISTS dss_tmp_postmeta;
DROP TABLE IF EXISTS dss_tmp_order_items;
DROP TABLE IF EXISTS dss_tmp_order_itemmeta;

DELETE FROM dss_options WHERE option_name LIKE '_transient_wc_%';
DELETE FROM dss_options WHERE option_name LIKE '_site_transient_wc_%';

Dies wird mit der fina­len SQL-Erfolgs-Rück­mel­dung quittiert:


Abfrage ausgeführt, 23 Datensätze betroffen. (0.017 s)
Reddit Reddit

Fina­ler Check nach so viel Datenbank-Arbeiten:

Damit wir sicher­stel­len kön­nen, dass der Del­ta-Abgleich kor­rekt funk­tio­niert hat, prü­fen wir das in unse­rer Word­Press Agen­tur für Woo­Com­mer­ce Sys­te­me mit dem fol­gen­den SQL-Befehl. Das gesam­te Vor­ge­hen arbei­tet kol­li­si­ons­frei, denn wir ver­schie­ben nur ech­te ID-Fel­der (nume­ri­sche Spal­ten). Das Feld meta_value bleibt bit­ge­nau unan­ge­tas­tet (das ist enorm wich­tig bei seria­li­sier­ten Daten). Man braucht kein manu­el­les Map­ping. Kol­li­sio­nen sind aus­ge­schlos­sen, weil alles ober­halb der aktu­el­len Maxi­ma lan­det. Das wird somit nur höhe­re Wer­te ein­spie­len. Daher nut­zen wir das sel­be Stich­da­tum, um die Daten “vor und nach dem Erstel­len des Ent­wick­lungs­ser­vers” abzugleichen.


-- Wie viele Orders sind neu dazugekommen?
SELECT COUNT(*) FROM dss_posts WHERE post_type='shop_order' AND post_date > '2025-12-05 11:55:15';

-- Stimmt die Referenzierung? (Items müssen auf existierende Orders zeigen)
SELECT COUNT(*) AS orphan_items
FROM dss_woocommerce_order_items oi
LEFT JOIN dss_posts p ON p.ID = oi.order_id
WHERE p.ID IS NULL;

Im SQL-Ergeb­nis soll­te orphan_items nun 0 sein.

Soll­ten Sie auch bei Ihrem Word­Press Sys­tem mit Woo­Com­mer­ce Shop einen sau­be­ren Trans­fer und Del­ta-Abgleich Ihrer Daten benö­ti­gen, kon­tak­tie­ren Sie uns jeder­zeit ger­ne. Wir hel­fen Ihnen ger­ne wei­ter und freu­en uns auf Ihre Anfrage.

Reddit Reddit

Per­sön­li­ches Gespräch gefällig?

Professor Doktor Alexander Lutz

Autor

Prof. Dr. Alex­an­der Lutz, Pro­fes­sor für Big Data und KI an der FOM Mün­chen, Dok­tor der Human­ge­ne­tik und Anthro­po­lo­gie, ehe­ma­li­ger Online­spie­le-Desi­gner und natür­lich Grün­der und Inha­ber der Agen­tur Die NEOs. Neben den The­men der künst­li­chen Intel­li­genz und deren Ein­satz­mög­lich­kei­ten in der Pra­xis kon­zen­triert sich Alex­an­der auf die Kun­den­kom­mu­ni­ka­ti­on. Neue Pro­blem­fel­der oder tech­ni­sche Inno­va­tio­nen berei­tet er so auf, dass der Nut­zen für unse­re Kun­den deut­lich wird. Er schläft zeit­ver­ant­wort­lich und agiert schnell, sein Mot­to: “Tue es, oder tue es nicht. Es gibt kein Ver­su­chen.”