Wie der Umzug von VSAM zu Postgres versteckte Schlüsselverträge bricht
Ein sicherer Umzug von VSAM zu Postgres bewahrt KSDS-Schlüsselbytes, Regeln alternativer Indizes, Lesereihenfolge und Batch-Verhalten.

Ein VSAM-KSDS-Schlüssel und ein Postgres-Primärschlüssel können denselben Geschäftssatz identifizieren und dennoch unterschiedliche Verträge durchsetzen. Wer sie für austauschbar hält, sieht vielleicht fehlerfreie Online-Masken. Das gilt genau bis zu dem Moment, in dem ein nächtliches Programm Datensätze in einer nie dokumentierten Reihenfolge liest, ein alternativer Index Duplikate anders liefert oder ein umgeschriebener Schlüssel bestimmt, welcher Satz als Nächstes kommt.
Die Bytes zu verschieben ist der einfache Teil. Die Migration gelingt nur, wenn Sie jeden Zugriffspfad finden und sein beobachtbares Verhalten nachbilden, bevor Sie das Schema verbessern. Dazu gehören unbequeme Details: Auffüllen auf feste Breiten, EBCDIC-Sortierung, Starts mit Teilschlüsseln, doppelte Alternativschlüssel, Aktualisierungen mehrerer Indizes und das Verhalten am Dateiende nach gleichzeitigen Änderungen. Ich habe Teams CRUD-Aufrufe testen und den Sieg erklären sehen, während der Batch-Bestand noch von den Eigenheiten des KSDS abhing.
Ein KSDS-Schlüssel ist ein Zugriffsvertrag, keine Spalte
Ein Postgres-Primärschlüssel drückt Eindeutigkeit und Zeilenidentität in einer relationalen Tabelle aus. Ein KSDS-Primärschlüssel steuert außerdem die Position in der logischen Folge, den Schlüsselzugriff, die Browse-Positionierung und Statusverhalten, auf das Anwendungscode vertraut. Diese Aufgaben überschneiden sich, sind aber nicht gleich.
In einem KSDS liegt der Schlüssel als Feld fester Länge an einem festgelegten Byte-Offset in jedem Datensatz. VSAM vergleicht dieses Feld gemäß den vorliegenden Daten und der Umgebung. Programme bauen den Schlüssel oft im Working Storage auf, füllen ihn auf, verschieben Anzeige- oder gepackte Werte hinein und übergeben ihn an COBOL-Dateioperationen oder CICS-Befehle. Die Bytes gehören zur Schnittstelle, auch wenn ein Copybook ihnen einen freundlichen Geschäftsnamen gibt.
Ein Postgres-PRIMARY KEY verlangt eindeutige Werte ungleich null und legt dafür einen eindeutigen B-Baum-Index an. Er sagt nichts darüber aus, ob '00123 ' und '00123' gleich sind, ob EBCDIC-Bytes genauso sortieren wie UTF-8-Text oder ob ein Aufrufer einen Browse nur mit dem führenden Teil eines zusammengesetzten Geschäftsschlüssels starten darf. Eine saubere relationale Definition kann deshalb für die migrierte Anwendung falsch sein.
Halten Sie bei der Analyse drei Identitäten getrennt. Der Datensatzschlüssel ist die genaue alte Bytefolge. Die Geschäftsidentität beschreibt, was der Datensatz für das Unternehmen bedeutet, etwa Konto plus Gültigkeitsdatum. Die Datenbankidentität ist der Schlüssel, den Sie in Postgres für Referenzen und Aktualisierungen wählen. Manchmal können alle drei zusammenfallen. Erzwingen Sie dieses Ergebnis nicht, bevor die Belege es tragen.
Die IBM-Dokumentation zu Key-Sequenced Data Sets beschreibt Datensätze als nach dem Schlüsselfeld geordnet und direkt oder sequenziell zugänglich. Die PostgreSQL-Dokumentation beschreibt einen Primärschlüssel als Eindeutigkeits- und Not-null-Constraint, der zugleich einen Index anlegt. Zusammen gelesen zeigen die Handbücher die Lücke: VSAM dokumentiert Zugriffsverhalten rund um einen Datensatz, Postgres eine relationale Einschränkung für einen Wert. Ihr Kompatibilitätsentwurf muss das fehlende Verhalten abdecken.
Erfassen Sie Aufrufe, nicht nur den Cluster-Katalog
Der Katalog zeigt vorhandene Basiscluster, alternative Indizes und Pfade. Er zeigt nicht, welche Programme von ihnen abhängen, welche Schlüsselformen diese Programme bauen oder was nach einem fehlgeschlagenen Start passiert. Erstellen Sie das Inventar aus Code, JCL, Transaktionsdefinitionen, Copybooks und Produktionsbeobachtungen.
Suchen Sie in COBOL nach READ, START, READ NEXT, READ PREVIOUS, REWRITE und DELETE für jede Dateibeschreibung. Durchsuchen Sie CICS-Code nach READ, STARTBR, READNEXT, READPREV, RESETBR, ENDBR, WRITE, REWRITE und DELETE und notieren Sie DATASET, RIDFLD, KEYLENGTH, GENERIC, GTEQ und Browse-Token. Finden Sie JCL-Schritte mit IDCAMS, SORT oder Hilfsprogrammen zum Kopieren, Entladen, Zusammenführen und Prüfen des Clusters. Beziehen Sie Assembler, PL/I, REXX und Scheduler-Skripte ein, falls sie dieselben Daten berühren.
Halten Sie für jede Operation fünf Punkte fest:
- Den verwendeten Pfad: Basiscluster oder benannter Alternativindexpfad.
- Die genauen Schlüsselbytes und die deklarierte oder übergebene Schlüssellänge.
- Operation und Positionierungsregel, einschließlich exakt, größer oder gleich, nächster und vorheriger.
- Erwartete Ergebnisform, Status und Duplikatverhalten.
- Den nachgelagerten Verbraucher, besonders einen Batch-Schritt oder Export.
Fassen Sie mehrere Aufrufer nicht in einer Zeile zusammen, nur weil sie dieselbe Datei nennen. Eine CICS-Auskunft, die eine exakte Kundennummer liest, und ein nächtlicher COBOL-Job, der an einem Filialpräfix startet, beanspruchen unterschiedliche Verträge. Letzterer kann sogar von der Reihenfolge der Duplikate unter einem Alternativschlüssel abhängen, obwohl niemand diese Reihenfolge als öffentlich vorgesehen hat.
Aufgezeichneter Produktionsverkehr hilft bei Online-Befehlen, verfehlt aber geplantes Verhalten und seltene Wiederherstellungszweige. Ergänzen Sie ihn durch statische Aufrufsuche und mindestens einen vollständigen Batch-Zyklus. Wenn die Monatsabschlussverarbeitung einen anderen JCL-Weg nutzt, erfassen Sie auch diesen. Ziel ist eine endliche Tabelle von Zugriffsverträgen, die Tests antreibt, nicht ein Architekturtext, den jeder anders auslegt.
Bytegleichheit und Textgleichheit trennen sich schnell
Bewahren Sie die ursprünglichen Schlüsselbytes, bis bewiesen ist, dass ein dekodierter Wert dasselbe Gleichheits- und Sortierverhalten hat. Zeichensatzkonvertierung ist eine semantische Änderung und keine Aufräumarbeit.
Nehmen wir einen zehn Byte langen Kundenschlüssel mit einem großgeschriebenen Regionscode, einer mit Nullen aufgefüllten Nummer und abschließenden Leerzeichen. Ein Loader könnte EBCDIC dekodieren, Leerzeichen abschneiden, die Nummer parsen und (region text, customer_no integer) speichern. Die neue Darstellung sieht besser aus. Sie verwirft aber möglicherweise Unterscheidungen des alten Programms, ändert Vergleiche für fehlerhafte Werte und verliert die exakten Bytes zur Erklärung einer Paritätsabweichung.
Die Kollation ist eine weitere Falle. Die Textsortierung in Postgres folgt der gewählten Datenbank- oder Spaltenkollation. Ein alter Browse sieht dagegen die Sortierung der codierten Schlüsselbytes und der VSAM-Umgebung. Buchstaben, Ziffern, Leerzeichen, Satzzeichen, unzulässig durchgerutschte Kleinbuchstaben und nationale Zeichen können anders einsortiert werden. ORDER BY key_text ist keine Kompatibilitätszusage, solange Tests sie nicht mit repräsentativen und absichtlich schwierigen Schlüsseln belegen.
Eine vorsichtige Landing-Tabelle hält die rohe Identität neben den geparsten Feldern:
CREATE TABLE customer_landing (
legacy_key bytea PRIMARY KEY,
record_image bytea NOT NULL,
region_code text,
customer_no bigint,
loaded_at timestamptz NOT NULL DEFAULT clock_timestamp(),
CHECK (octet_length(legacy_key) = 10)
);
CREATE UNIQUE INDEX customer_business_identity
ON customer_landing (region_code, customer_no)
WHERE region_code IS NOT NULL AND customer_no IS NOT NULL;
Der Rohschlüssel ermöglicht verlustfreie Suche und liefert einen stabilen Diagnosegriff. Geparste Spalten tragen das beabsichtigte Modell. Der partielle eindeutige Index prüft eine Geschäftshypothese, ohne zu behaupten, dass jeder historische Satz sauber ist. Scheitert die Hypothese beim Laden, haben Sie Daten gefunden, für die eine ausdrückliche Regel nötig ist. Sie haben kein Ärgernis gefunden, das mit ON CONFLICT DO NOTHING verschwinden sollte.
Für einen textkompatiblen Rohschlüssel können Sie eine feste Normalisierungsfunktion und binäre Kollation verwenden. Dokumentieren Sie aber jede Transformation und testen Sie deren Umkehrung. Für gemischte oder gezonte Daten ist bytea meist die ehrliche erste Darstellung. Später können Sie es entfernen, wenn die Paritätstests beweisen, dass kein Aufrufer den Unterschied beobachtet. Belege vor der Parität zu entfernen, kehrt die Reihenfolge um.
Alternative Indizes haben eigene Semantik
Ein alternativer Index ist nicht bloß ein sekundärer Postgres-Index. Er ist ein weiterer Zugriffspfad mit eigener Schlüsselextraktion, Eindeutigkeitsregel, Duplikatbehandlung und Browse-Reihenfolge, den Programme über einen Pfad sehen.
IDCAMS kann einen alternativen Index mit eindeutigen oder nicht eindeutigen Schlüsseln definieren. Bei nicht eindeutigen Alternativschlüsseln teilen sich mehrere Basissätze denselben Alternativwert. Ein Aufrufer kann sich auf diesem Wert positionieren und die passenden Sätze durchlaufen. Ein einfacher Postgres-Index auf surname beschleunigt die Suche, legt aber keine deterministische Reihenfolge zwischen gleichen Nachnamen fest. Der Planner kann Gleichstände nach Vacuum, Indexneuaufbau, Planwechsel oder Datenverschiebung anders liefern. SQL verspricht ohne ein ORDER BY, das Gleichstände auflöst, keine Reihenfolge.
Modellieren Sie jeden Alternativpfad ausdrücklich. Angenommen, die Altanwendung durchsucht Policen nach Vermittlercode und hat innerhalb eines Vermittlers bisher die Reihenfolge des Basisschlüssels gesehen. Codieren Sie beide Teile im Kompatibilitätsindex und in der Abfrage:
CREATE INDEX policy_by_agent_legacy
ON policy (agent_key_bytes, legacy_key);
SELECT legacy_key, record_image
FROM policy
WHERE (agent_key_bytes, legacy_key) >= ($1::bytea, $2::bytea)
AND agent_key_bytes = $1::bytea
ORDER BY agent_key_bytes, legacy_key
LIMIT $3;
Unterstellen Sie die Sekundärreihenfolge nicht. Messen Sie sie am Quellpfad, einschließlich in verschiedener Folge erzeugter Duplikatgruppen und Datensätze, deren Alternativschlüssel nachträglich geändert wurde. Hängt die beobachtete Reihenfolge von einem internen VSAM-Detail ab, das Sie nicht reproduzieren können oder sollten, machen Sie diese Inkompatibilität ausdrücklich und ändern Sie den Verbraucher kontrolliert. Ein während der Migration unerklärtes ORDER BY ersetzt nur eine versteckte Abhängigkeit durch eine andere.
Aktualisierungen verdienen besondere Aufmerksamkeit. Ändert ein REWRITE ein Alternativschlüsselfeld, pflegt VSAM den alternativen Index gemäß Definition und Upgrade-Einstellung. In Postgres muss eine generierte Spalte, ein Trigger oder der Anwendungsschreibweg den passenden Wert atomar mit dem Datensatz ändern. Falls ein Dienst das geparste Feld schreibt und ein anderer Rohbilder importiert, zentralisieren Sie die Schlüsselableitung in einer getesteten Funktion. Zwei Implementierungen werden irgendwann bei Auffüllung oder ungültigen Bytes auseinanderlaufen.
Erfassen Sie auch Pfade, die existieren, aber unbenutzt wirken. Manche sind Wiederherstellungswerkzeuge oder Prüfexporte, die nur nach einem Fehler laufen. Markieren Sie sie mit Belegen als ruhend. Entfernen Sie sie nicht stillschweigend, weil dreißig Tage Online-Traces keinen Aufruf zeigten.
Browse-Zustand braucht eine ausdrückliche Cursorregel
Ein VSAM-Browse ist aus Sicht des Aufrufers zustandsbehaftet. SQL-Abfragen arbeiten mit Mengen. Der Ersatz muss deshalb Positionierung und Fortsetzung definieren, statt sich auf Verbindungszustand oder Offset-Paginierung zu verlassen.
START oder STARTBR kann einen exakten Schlüssel, ein generisches Präfix oder den ersten Schlüssel größer oder gleich den übergebenen Bytes anfordern. Weitere Next- und Previous-Aufrufe bewegen sich relativ zu dieser Position. Anwendungen beachten Randverhalten: ob der Start einen Datensatz liefert, nur eine Position festlegt, Nicht gefunden meldet oder den Browse ans Dateiende setzt. Ihr Adapter sollte den Vertrag jedes tatsächlich verwendeten Aufrufers nachbilden.
Verwenden Sie Keyset-Paginierung mit dem vollständigen alten Sortiertupel. Bei einem Vorwärts-Browse auf (alternate_key, base_key) geben Sie beide Werte in einem opaken Cursor zurück und setzen mit einem strikten Vergleich fort:
SELECT alternate_key, legacy_key, record_image
FROM customer
WHERE (alternate_key, legacy_key) > ($1::bytea, $2::bytea)
ORDER BY alternate_key, legacy_key
LIMIT $3;
Für einen Start mit größer oder gleich verwenden Sie >= nur in der ersten Anfrage. Fortsetzungen nutzen >, damit die letzte Zeile nicht erneut erscheint. Rückwärts-Browses kehren Vergleich und Sortierung um. Offset-Paginierung ist hier falsch, weil Einfügungen und Löschungen vor dem Offset das Fenster verschieben und ein großer Offset Postgres durch bereits verbrauchte Zeilen laufen lässt.
Teilschlüssel brauchen eine Grenze auf Byteebene und kein beiläufiges LIKE 'ABC%'. Berechnen Sie für ein festes Binärpräfix eine Untergrenze aus dem Präfix mit minimalem Suffix und eine exklusive Obergrenze aus dem nächsten möglichen Präfix. Existiert kein nächstes Präfix, weil jedes Byte maximal ist, verwenden Sie nur die Untergrenze und prüfen das Präfix der gelieferten Schlüssel. Legen Sie die Logik in einen Adapter und testen Sie leere, nur aus Nullbytes bestehende, maximale und Leerzeichen enthaltende Fälle.
Nebenläufigkeit erzwingt eine Richtlinie. Ein langer VSAM-Browse und mehrere zustandslose SQL-Anfragen können Einfügungen und Löschungen anders sehen. Entscheiden Sie, ob der Ersatz eine Repeatable-Read-Transaktion hält, eine Arbeitsliste materialisiert oder eine bewegliche Sicht mit Keyset-Fortsetzung akzeptiert. Bilden Sie das Quellverhalten nach, das der Geschäftsprozess verlangt, nicht ein theoretisches Bild von VSAM. Eine Datenbanktransaktion über die Bildschirmsitzung eines Bedieners zu halten ist meist ein schlechter Tausch. Schlüssel für einen begrenzten Batch zu materialisieren funktioniert oft gut.
Im Nacht-Batch wird Sortierung zur Geschäftslogik
Batch-Programme verwenden sortierte Eingaben oft als Kontrollfluss. Das Programm erkennt einen Schlüsselwechsel, schreibt Summen, öffnet eine neue Berichtsgruppe, trägt einen vorherigen Satz weiter oder führt zwei Dateien zusammen, indem es jeweils den kleineren Schlüssel vorrückt. Ändert sich die Reihenfolge, ändert sich die Berechnung, obwohl jeder Satz angekommen ist.
Ein typischer Fehler beginnt harmlos. Die Migration exportiert alle Zeilen aus Postgres, Anzahl und Prüfsummen stimmen, und die Online-API besteht Exaktschlüsseltests. Um 1:00 Uhr liest ein Job Policen über einen Alternativpfad nach Filiale. Gleiche Filialschlüssel kommen in einer anderen Basisschlüsselreihenfolge. Das Programm ordnet jede Police in einem Ein-Pass-Merge dem nächsten Transaktionssatz zu. Ein Satz ist nun kleiner als der gespeicherte Transaktionsschlüssel, fällt in einen Ausnahmezweig und verhindert den Ausgleich der Kontrollsumme. Die Datenbank ist verfügbar, der Batch ist trotzdem kaputt.
Ein weiterer Fehler stammt aus impliziter SQL-Reihenfolge. Ein Entwickler testet SELECT ... FROM policy WHERE status = 'A' und sieht Primärschlüsselreihenfolge, weil der gewählte Plan zufällig einen Index scannt. Produktionsstatistiken bevorzugen später einen sequenziellen Scan. Dieselben Zeilen erscheinen in Heap-Reihenfolge. PostgreSQL stellt klar, dass Zeilen ohne ORDER BY keine garantierte Ordnung haben. Der Test hat versehentlich einen Plan bestätigt, nicht den Vertrag.
Machen Sie aus jeder konsumierten Folge ein ausdrücklich beschriebenes Datenprodukt. Notieren Sie Quellpfad, vollständiges Sortiertupel, Codierung, Duplikatregel und Snapshot-Grenze. Die Exportabfrage muss alle Punkte nennen. Liest der Batch historisch eine von einem vorherigen Schritt eingefrorene Generation, richten Sie ihn nicht auf Live-Tabellen und hoffen auf dieselbe Grenze durch Transaktionsisolation. Erstellen Sie eine laufbezogene Staging-Tabelle oder exportieren Sie unter einem deklarierten Snapshot.
Ein nützliches Paritätsartefakt vergleicht geordnete Streams und nicht nur ungeordnete Hashes:
run_id: 2026-08-14-nightly
path: POLICY.BY.BRANCH
snapshot_cutoff: 2026-08-14T01:00:00Z
record_count: 184203
first_key_hex: C1F0F0F0F0F0F0F1
last_key_hex: E9F9F9F9F9F9F9F9
rolling_digest: sha256:<digest>
first_mismatch_position: <none|integer>
source_key_hex: <hex when mismatched>
target_key_hex: <hex when mismatched>
Das Format zeigt, an welcher Stelle die Gleichheit endete. Genau das braucht ein Ingenieur in der Nacht. Bilden Sie den Digest über längenpräfixierte Schlüssel- und Datensatzbytes, damit Feldgrenzen nicht kollidieren. Bewahren Sie Gruppenzahlen und Summen auf, wo der Batch Kontrollwechsel nutzt. Eine einzelne Prüfsumme für die ganze Datei sagt, dass sich etwas änderte. Sie sagt nicht, welcher Zugriffsvertrag scheiterte.
Schreibverhalten zählt ebenso wie Lesen
Schreibvorgänge müssen Schlüsselunveränderlichkeit, Duplikatabweisung, Indexpflege und Statusabbildung in einer Transaktion bewahren. Eine Migration kann Daten korrekt kopieren und dennoch den morgigen Browse beschädigen, wenn die erste Online-Aktualisierung anderen Regeln folgt.
Viele KSDS-Anwendungen ändern den primären Datensatzschlüssel bei REWRITE nicht. Sie löschen den Satz und schreiben einen neuen. Eine relationale API könnte beiläufig UPDATE ... SET id = ... erlauben. Entscheiden Sie, ob die Kompatibilitätsschicht Schlüsseländerungen ablehnt oder die alten Lösch- und Neuanlagefolgen samt Alternativindizes und Auditverhalten umsetzt. Lassen Sie kein ORM entscheiden.
Bilden Sie erwartete Fehler bewusst ab. Doppelter Primärschlüssel, doppelter eindeutiger Alternativschlüssel, fehlender Satz, veraltete Aktualisierung und Browse-Ende sind Anwendungsergebnisse, keine beliebigen internen Fehler. Postgres-SQLSTATE-Werte helfen im Adapter, aber sie an alte COBOL-Aufrufer durchzureichen ändert Zweige für Wiederholungen oder Bedienermeldungen. Bauen Sie eine kleine Zuordnungstabelle und testen Sie den exakten Status jeder Operation.
Auch Sperrverhalten unterscheidet sich. Eine Quelltransaktion könnte einen Satz zur Aktualisierung lesen, ändern und innerhalb einer Arbeitseinheit zurückschreiben. Das Ziel braucht eine entsprechende Regel, häufig SELECT ... FOR UPDATE gefolgt von einer Aktualisierung mit Versionsprüfung. Für getrennte Clients kann eine optimistische Versionsspalte verhindern, dass eine alte Maske einen neueren Satz überschreibt. Das ist eine Modernisierung, muss aber den vom Altaufrufer erwarteten sichtbaren Status liefern, bis dieser geändert wird.
Doppelschreiben nach VSAM und Postgres ist eine beliebte Sicherheitsempfehlung. Ich halte es nicht für den Standardweg. Zwei Systeme mit verschiedenen Constraints und Sortierregeln schaffen ein drittes Abstimmungsproblem, besonders wenn ein Teilfehler einen Alternativschlüssel nur auf einer Seite ändert. Ein aufgezeichnetes Änderungslog mit Replay und gemessener Verzögerung kann für die Umschaltung sinnvoll sein. Eine offene Doppelschreibphase verschleiert jedoch die Zuständigkeit. Bevorzugen Sie einen Schreiber an einer festgelegten Umschaltgrenze und einen geprobten Rollback, der den alten Schreiber wieder einsetzt und akzeptierte Änderungen nachspielt.
Parität muss Operationen, Folgen und Fehler abdecken
Der Vergleich einzelner Datensätze ist nötig und reicht nicht aus. Der Paritätstest muss die Operationen der Anwendungen ausführen, geordnete Folgen beobachten und Fehlerverhalten vergleichen.
Erstellen Sie Fixtures, die beiden Systemen unangenehm sind: minimale und maximale Schlüsselbytes, führende und abschließende Leerzeichen, numerischer Text mit führenden Nullen, doppelte Alternativschlüssel, fehlende optionale Felder, ungültige historische Codierungen, Schlüssel neben einer Präfixgrenze und umgeschriebene Sätze mit verschobenem Alternativschlüssel. Ergänzen Sie danach einen kleinen Zufallsgenerator. Zufallsabdeckung darf aber nie benannte Fixtures ersetzen, die einen Fehler erklären.
Führen Sie für jeden Zugriffsvertrag diese Folge aus:
- Laden Sie identische Datensatzbilder in Quell-Fixture und Ziel-Landing-Modell.
- Führen Sie die im Inventar gültigen exakten, größer-oder-gleich-, Präfix-, Next- und Previous-Operationen aus.
- Vergleichen Sie gelieferte Schlüsselbytes, Datensatzbytes, Status, Reihenfolge und Endbedingungen.
- Wenden Sie Writes, Rewrites, Änderungen an Alternativschlüsseln und Löschungen an und wiederholen Sie die Lesevorgänge.
- Führen Sie den verbrauchenden Batch aus und vergleichen Sie Berichte, Kontrollsummen, Ablehnungen und Neustartdaten.
Nutzen Sie aufgezeichneten Produktionsverkehr als weiteren Fixture-Satz, nachdem vertrauliche Felder nach Kundenregeln entfernt oder geschützt wurden. CodeHero prüft umgeschriebenes Verhalten mit einem Paritätstest gegen aufgezeichneten Produktionsverkehr. Die Analyse des ganzen Codebestands hilft hier, weil der Vertrag COBOL, JCL, Hilfsprogramme und Copybooks umfasst, statt in einem Repository-Ordner zu liegen. Synthetische Randfälle oder komplette Batch-Läufe werden dadurch nicht überflüssig.
Definieren Sie die Abnahme je Pfad. Eine Exaktsuche kann byteidentische Ausgabe und Status verlangen. Ein modernisierter Bericht kann Formatänderungen erlauben, aber identische Gruppenzuordnung und Summen fordern. Ein korrigierter Defekt braucht eine genehmigte Abweichung statt einer versteckten Ausnahme im Vergleicher. Speichern Sie diese Entscheidungen beim Test, damit eine spätere Schemabereinigung keine Kompatibilitätsregel versehentlich löscht.
Führen Sie Leistungstests mit denselben Zugriffsformen aus. Eine Abfrage, die nach einem vollständigen Tabellenscan die korrekte erste Seite liefert, wird unter Batch-Last scheitern. Prüfen Sie EXPLAIN (ANALYZE, BUFFERS) bei repräsentativen Größen, stellen Sie passende zusammengesetzte Indizes für Vergleiche und Sortierung sicher und testen Sie schiefe Alternativschlüssel, bei denen ein Wert viele Sätze besitzt. Korrektheit kommt zuerst, aber ein Browse außerhalb seines Nachtfensters ist betrieblich falsch.
Neustartzustand gehört zum Datenvertrag
Eine Batch-Umschaltung muss erhalten, wo Arbeit wiederaufgenommen werden kann, und nicht nur, welche Zeilen die neue Datenbank enthält. Alte Jobs setzen Prüfpunkte oft mit letztem Schlüssel, Satzzahl, Kontrollsumme, Generationsnamen oder Scheduler-Flag. Deren Bedeutung hängt von der Quellreihenfolge ab. Ändert das Ziel diese Reihenfolge, kann derselbe Prüfpunkt Zeilen überspringen oder doppelt verarbeiten.
Verfolgen Sie zuerst Neustartdaten durch den gesamten Jobstrom. Ein COBOL-Programm könnte den letzten fertigen Filial- und Policenschlüssel in eine kleine Datei schreiben, während JCL-Dispositionen festlegen, ob sie einen Abbruch überlebt. Ein späterer Schritt löscht den Prüfpunkt vielleicht erst, nachdem Berichte kopiert wurden und Kontrollsummen stimmen. Primärdaten nach Postgres zu verschieben, ohne diese Commit-Grenzen nachzubilden, macht aus einem behebbaren Fehler einen unsicheren Wiederholungslauf.
Übersetzen Sie eine Quelldatensatzposition nie in einen Postgres-Offset. Relative Byteadressen und Kontrollintervallpositionen gehören zur VSAM-Implementierung. SQL-Offsets sind bei Änderungen instabil. Wandeln Sie Neustartzustand in das vollständige logische Sortiertupel um, etwa (branch_key_bytes, policy_key_bytes), ergänzt um Batch-Laufidentität und Snapshot-Grenze. Setzen Sie mit einem strikten Vergleich nach dem letzten bestätigten Tupel fort. Liest das alte Programm den Prüfpunkt absichtlich erneut und erkennt ihn als Duplikat, bewahren Sie diese Regel im Adapter, statt still >= in > zu ändern.
Prüfpunkt und geschützte Geschäftseffekte brauchen eine atomare Grenze. Aktualisiert ein Batch Postgres direkt, speichern Sie Ergebniszeilen, Summen und nächsten Cursor möglichst in derselben Transaktion. Erzeugt er Dateien für spätere Schritte, schreiben Sie laufbezogene Ausgaben und veröffentlichen sie erst nach dem Datenbank-Commit. Ein vor der endgültigen Ablage der Ausgabedatei vorgerückter Cursor erzeugt eine Lücke. Eine vor dem Cursor-Commit veröffentlichte Ausgabe erzeugt beim Neustart ein Duplikat.
Testen Sie Unterbrechung praktisch. Beenden Sie den Zielprozess nach der ersten Zeile, mitten in einer Gruppe doppelter Alternativschlüssel, direkt vor einer Gruppensumme, nach dem Datenbank-Commit aber vor der Ausgabeveröffentlichung und während der abschließenden Prüfpunktbereinigung. Starten Sie aus dem erfassten Zustand neu und vergleichen Sie die Endartefakte mit einem ununterbrochenen Quelllauf. Zwischenarbeit muss nicht immer byteidentisch sein. Akzeptierte Sätze, Ablehnungen, Summen und veröffentlichte Ausgabe müssen aber dem erklärten Vertrag entsprechen.
Auch der Rollback bei der Umschaltung braucht diese Disziplin. Notieren Sie eine Hochwassermarke für akzeptierte Änderungen, stoppen oder sperren Sie Schreiber, lassen Sie laufende Arbeit auslaufen und beweisen Sie vor dem Batch-Fenster, welches System Schreibhoheit hat. Gibt der Rollback die Hoheit an VSAM zurück, spielen Sie nur Änderungen nach dessen bestätigter Hochwassermarke ein und prüfen danach die Alternativpfade. Die vage Anweisung, Datenverkehr zurückzuschalten, behandelt weder Warteschlangentransaktionen noch teilweise veröffentlichte Exporte oder gegen die Zielsortierung erzeugte Prüfpunkte.
Geben Sie dem Betrieb ein Runbook mit konkreten Belegen: Schreibhoheit, Quell- und Ziel-Hochwassermarken, aktive Batch-Lauf-IDs, letztes bestätigtes Sortiertupel, Veröffentlichungsstatus der Ausgaben und Befehl oder Abfrage für jeden Wert. Proben Sie es mit denselben Scheduler-Abhängigkeiten wie in Produktion. Der schlechteste Zeitpunkt für die Erkenntnis, dass eine Neustartdatei einen getrimmten Zeichenschlüssel enthält, ist nach dem ersten Abbruch auf dem Ziel.
Modernisieren Sie erst an einer stabilen Kompatibilitätsgrenze
Das erste sichere Postgres-Modell kann weniger elegant aussehen als das endgültige. Rohschlüssel, Datensatzbilder, ausdrückliche Kompatibilitätsindizes und Adapter bewahren Belege, während Sie das Verhalten beweisen. Sobald Parität besteht, modernisieren Sie hinter dieser Grenze in messbaren Änderungen.
Ein brauchbares Ziel hat oft drei Schichten. Die Landing-Schicht speichert verlustfreie importierte Bytes und Quellmetadaten. Die Kompatibilitätsschicht implementiert alte Lesevorgänge, Browses, Status und geordnete Exporte. Die Domänenschicht bietet typisierte relationale Tabellen und APIs für neuen Code. Diese Schichten können eine Datenbank teilen, ihre Verträge unterscheiden sich aber. Neue Dienste sollten keine rohen Copybook-Bytes parsen. Alte Aufrufer sollten keinen direkten Zugriff auf Tabellen bekommen, deren Schlüssel sich noch ändern.
Wählen Sie den dauerhaften Primärschlüssel nach Zuständigkeit. Ist der alte Schlüssel stabil, kompakt und identifiziert die Entität wirklich, kann seine Beibehaltung sinnvoll sein. Enthält er veränderliche Attribute, überladene Typcodes oder Darstellungspolster, nutzen Sie einen Surrogatschlüssel und bewahren den Altschlüssel unter einem eindeutigen Constraint. Fremdschlüssel sollten auf die Identität zeigen, die stabil bleibt, wenn das Geschäft einen Code korrigiert. Das ist eine Datenmodellentscheidung und keine Pauschalregel zugunsten natürlicher oder künstlicher Schlüssel.
Bauen Sie Kompatibilität Abhängigkeit für Abhängigkeit ab. Stellen Sie einen Verbraucher auf eine Domänen-API mit dokumentierter Sortierung um, lassen Sie beide Wege durch Parität laufen und entfernen Sie dann seinen Altpfad aus dem Inventar. Erst wenn kein Aufrufer Byteordnung braucht, sollten Sie rohe Schlüsselindizes oder Datensatzbilder löschen. Speicher ist billig verglichen mit der Rekonstruktion, warum ein Jahresendjob einst 9 vor A sortierte.
Der Migrationsplan muss den Nacht-Batch als vollwertigen Verbraucher mit Eigentümer, Testfenster, Neustartverfahren und Rollback-Grenze nennen. Steht dort nur, das KSDS werde eine Tabelle, ist die Arbeit nicht beschrieben. Ein vertrauenswürdiger Plan nennt verbleibende Byteverträge, bewusst geändertes Verhalten und den Test, der jede Entscheidung beweist, bevor der alte Cluster seine Rolle als führendes System verliert.
FAQ
Kann ein VSAM-KSDS-Schlüssel direkt zum Postgres-Primärschlüssel werden?
Manchmal, aber erst wenn Bytegleichheit, Eindeutigkeit, Sortierung und Änderungsregeln alle Paritätstests bestehen. Bewahren Sie bei der Migration die Originalbytes, auch wenn Sie zusätzlich eine sauberere typisierte Identität schaffen.
Warum zählt die EBCDIC-Sortierung nach der Umwandlung in UTF-8 noch?
Batch- und Browse-Logik können die alte Bytefolge beobachten, während Postgres-Text eine Kollation über dekodierte Zeichen nutzt. Sichtbar gleiche Werte können deshalb anders eintreffen und andere Kontrollwechsel auslösen.
Wie speichert man doppelte VSAM-Alternativschlüssel in Postgres?
Verwenden Sie einen nicht eindeutigen Index mit Alternativschlüssel und einem am Quellpfad belegten Tie-Breaker. Fragen Sie mit ORDER BY über das vollständige Tupel ab. Ein Index nur auf dem Alternativwert definiert keine Duplikatreihenfolge.
Reichen gleiche Satzzahlen und Prüfsummen für eine VSAM-Migration?
Nein. Diese Prüfungen übersehen Sortierung, Positionierung, Statuscodes, Teilschlüsselverhalten und Indexpflege nach Änderungen. Vergleichen Sie geordnete Operationsergebnisse und führen Sie den echten verbrauchenden Batch aus.
Was ersetzt STARTBR und READNEXT in Postgres?
Ein Kompatibilitätsadapter bildet sie meist auf Keyset-Abfragen über das vollständige alte Sortiertupel ab. Die erste Abfrage setzt eine exakte oder größer-oder-gleich Position, spätere setzen strikt nach dem zuletzt gelieferten Tupel fort.
Soll eine Migration Leerzeichen aus VSAM-Schlüsseln abschneiden?
Nicht in der verlustfreien Darstellung. Sie dürfen normalisierte Geschäftsspalten ergänzen, aber frühes Abschneiden kann verschiedene Byte-Schlüssel zusammenführen und Sortiergrenzen ändern.
Kann Postgres Zeilen ohne ORDER BY in Primärschlüsselreihenfolge liefern?
Im Test kann es so aussehen, SQL garantiert diese Ordnung aber nicht. Planwechsel, Vacuum oder Tabellenneuschreiben können eine andere Folge erzeugen. Jeder ordnungsabhängige Verbraucher braucht ein ausdrückliches ORDER BY.
Soll man bei der Umschaltung gleichzeitig nach VSAM und Postgres schreiben?
Nur mit einem definierten Abstimmungsentwurf und kurzem Zuständigkeitswechsel. Für die meisten Bestände schaffen ein erklärter Schreiber, aufgezeichnete Änderungen, Replay und ein geprobter Rollback weniger mehrdeutige Fehlerfälle.
Wie testet man VSAM-Browses mit Teilschlüsseln?
Bilden Sie untere und obere Grenzen auf Byteebene und vergleichen Sie Rand-Fixtures mit der Quelle. Decken Sie leere Präfixe, Leerzeichen, Nullbytes, maximale Bytes, fehlende Treffer und Duplikate an beiden Enden ab.
Wann darf das rohe VSAM-Datensatzbild gelöscht werden?
Erst wenn jeder Aufrufer den Kompatibilitätspfad verlassen hat und erhaltene Tests die nötige Abdeckung des typisierten Modells beweisen. Bis dahin ist das Rohbild der Beleg für die Diagnose von Konvertierungs- und Paritätsfehlern.