Comment le passage de VSAM à Postgres brise des contrats cachés
Passer de VSAM à Postgres sans risque exige de préserver les octets KSDS, les index alternatifs, l'ordre de lecture et les traitements batch.

Une clé KSDS de VSAM et une clé primaire Postgres peuvent identifier le même enregistrement métier tout en imposant des contrats différents. Les traiter comme des équivalents peut laisser les écrans en ligne fonctionner correctement, jusqu'au moment où un programme nocturne parcourt les enregistrements dans un ordre que personne n'a documenté, où un index alternatif renvoie les doublons autrement, ou encore où une clé réécrite change l'enregistrement suivant.
Déplacer les octets est la partie facile. La migration ne réussit que si vous trouvez chaque chemin d'accès et reproduisez son comportement observable avant d'améliorer le schéma. Cela comprend des détails gênants: remplissage à largeur fixe, ordre EBCDIC, démarrages sur clé partielle, clés alternatives en double, mises à jour qui entretiennent plusieurs index et comportement de fin de fichier après des modifications concurrentes. J'ai vu des équipes tester les appels CRUD et déclarer victoire alors que le parc batch dépendait encore de la personnalité physique du KSDS.
Une clé KSDS est un contrat d'accès, pas une colonne
Une clé primaire Postgres exprime l'unicité et l'identité d'une ligne dans une table relationnelle. Une clé primaire KSDS commande aussi la place dans la séquence logique, l'accès par clé, la position de parcours et les statuts attendus par le code applicatif. Ces fonctions se recoupent, mais elles ne sont pas identiques.
Dans un KSDS, la clé est un champ fixe situé à un décalage et sur une longueur en octets déclarés dans chaque enregistrement. VSAM compare ce champ selon les données et l'environnement qui lui sont présentés. Les programmes construisent souvent la clé dans la working storage, la complètent, y déplacent des valeurs d'affichage ou compactées, puis la passent à des opérations de fichier COBOL ou à des commandes CICS. Les octets font partie de l'interface même si un copybook leur donne un nom métier rassurant.
Une PRIMARY KEY Postgres exige que chaque valeur soit unique et non nulle, et Postgres la soutient par un index B-tree unique. Cela ne dit pas si '00123 ' égale '00123', si les octets EBCDIC se trient comme du texte UTF-8, ni si un appelant peut commencer un parcours avec seulement le début d'une clé métier composite. Une définition relationnelle propre peut donc être fausse pour l'application migrée.
Séparez trois identités pendant l'analyse. La clé d'enregistrement est la séquence exacte d'octets héritée. L'identité métier correspond à ce que l'organisation dit que l'enregistrement signifie, par exemple un compte et une date d'effet. L'identité de base est la clé retenue pour les références et les mises à jour dans Postgres. Les trois peuvent parfois converger. Ne forcez pas ce résultat avant que les preuves le permettent.
La documentation IBM sur les jeux de données séquencés par clé décrit des enregistrements ordonnés par le champ de clé et accessibles directement ou séquentiellement. La documentation PostgreSQL définit une clé primaire comme une contrainte d'unicité et de non-nullité qui crée aussi un index. Lues ensemble, ces notices montrent l'écart: VSAM documente un comportement d'accès autour d'un enregistrement, Postgres une contrainte relationnelle autour d'une valeur. Votre conception de compatibilité doit combler ce comportement absent.
Inventoriez les appels, pas seulement le catalogue
Le catalogue indique quels clusters de base, index alternatifs et chemins existent. Il ne dit pas quels programmes en dépendent, quelles formes de clé ils construisent, ni ce qu'ils font après un démarrage infructueux. Construisez l'inventaire à partir du code, du JCL, des définitions de transaction, des copybooks et des observations de production.
Cherchez dans le COBOL READ, START, READ NEXT, READ PREVIOUS, REWRITE et DELETE pour chaque description de fichier. Dans le code CICS, cherchez READ, STARTBR, READNEXT, READPREV, RESETBR, ENDBR, WRITE, REWRITE et DELETE, puis relevez DATASET, RIDFLD, KEYLENGTH, GENERIC, GTEQ et les jetons de parcours. Trouvez les étapes JCL qui utilisent IDCAMS, SORT ou des utilitaires pour copier, décharger, fusionner et valider le cluster. Incluez Assembleur, PL/I, REXX et les scripts de planification s'ils touchent les mêmes données.
Pour chaque opération, consignez cinq éléments:
- Le chemin utilisé: cluster de base ou chemin nommé d'index alternatif.
- Les octets exacts de la clé et sa longueur déclarée ou fournie.
- L'opération et la règle de positionnement, dont exact, supérieur ou égal, suivant et précédent.
- La forme de résultat attendue, le statut et le traitement des doublons.
- Le consommateur en aval, surtout une étape batch ou un export.
Ne fusionnez pas plusieurs appelants sur une même ligne parce qu'ils nomment le même fichier. Une consultation CICS qui lit un numéro de client exact et un job COBOL nocturne qui démarre sur un préfixe d'agence sollicitent des contrats différents. Le second peut aussi dépendre de l'ordre des doublons sous une clé alternative, même si personne n'avait prévu de rendre cet ordre public.
Le trafic de production enregistré aide pour les commandes en ligne, mais il manque les traitements planifiés et les branches de reprise rares. Associez-le à la découverte statique des appels et à au moins un cycle batch complet. Si la clôture mensuelle suit un autre chemin JCL, capturez-le aussi. Le but est une table finie de contrats d'accès capable de piloter les tests, pas un document d'architecture que chacun interprétera autrement.
L'égalité des octets diverge vite de celle du texte
Conservez les octets de clé d'origine jusqu'à avoir prouvé qu'une valeur décodée possède les mêmes comportements d'égalité et de tri. La conversion de caractères change la sémantique, ce n'est pas du rangement.
Prenons une clé client de dix octets contenant un code de région en majuscules, un numéro complété par des zéros et des espaces finaux. Un chargeur pourrait décoder l'EBCDIC, supprimer les espaces, convertir le numéro et stocker (region text, customer_no integer). La nouvelle représentation paraît meilleure. Elle peut pourtant supprimer des distinctions produites par l'ancien programme, modifier les comparaisons de valeurs mal formées et perdre les octets exacts nécessaires pour expliquer un écart de parité.
Le classement ajoute un autre piège. Dans Postgres, l'ordre du texte suit le classement choisi pour la base ou la colonne, tandis qu'un parcours historique observe l'ordre produit par les octets de la clé encodée et l'environnement VSAM. Lettres, chiffres, espaces, ponctuation, minuscules passées malgré les contrôles et caractères nationaux peuvent changer de place. ORDER BY key_text n'est pas une promesse de compatibilité tant que des tests ne l'ont pas prouvé sur des clés représentatives et hostiles.
Une table d'atterrissage prudente garde l'identité brute à côté des champs analysés:
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;
La clé brute assure une recherche sans perte et donne une poignée de diagnostic stable. Les colonnes analysées portent le modèle voulu. L'index unique partiel teste une hypothèse métier sans prétendre que tous les enregistrements historiques sont propres. Si l'hypothèse échoue pendant le chargement, vous avez trouvé des données qui demandent une règle explicite, pas une gêne à masquer avec ON CONFLICT DO NOTHING.
Pour une clé brute compatible avec du texte, vous pouvez employer une fonction de normalisation fixe et un classement binaire, mais documentez chaque transformation et testez son inverse. Pour des données mixtes ou zonées, bytea est souvent la première représentation honnête. Vous pourrez l'abandonner après que la suite de parité aura prouvé qu'aucun appelant n'observe la différence. Supprimer les preuves avant la parité prend le problème à l'envers.
Les index alternatifs portent leur propre sémantique
Un index alternatif n'est pas un simple index secondaire Postgres. C'est un autre chemin d'accès, avec sa propre extraction de clé, sa règle d'unicité, son traitement des doublons et son ordre de parcours, exposé aux programmes par un chemin.
IDCAMS peut définir un index alternatif avec des clés uniques ou non uniques. Avec des clés alternatives non uniques, plusieurs enregistrements de base partagent la même valeur alternative. Un appelant peut se positionner sur cette valeur et parcourir les enregistrements correspondants. Un simple index Postgres sur surname accélère la recherche, mais ne fixe aucun ordre déterministe entre les noms identiques. Le planificateur peut renvoyer les égalités dans un ordre différent après un vacuum, une reconstruction d'index, un changement de plan ou un déplacement de données. SQL ne promet aucun ordre sans un ORDER BY qui départage les égalités.
Modélisez chaque chemin alternatif explicitement. Imaginons que l'ancienne application parcoure les polices par code d'agent et ait historiquement observé l'ordre de la clé de base au sein d'un agent. Encodez les deux parties dans l'index de compatibilité et la requête:
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;
Ne supposez pas l'ordre secondaire. Mesurez-le sur le chemin source, avec des groupes de doublons créés dans des séquences différentes et des enregistrements dont la clé alternative a changé après création. Si l'ordre observé dépend d'un détail interne de VSAM que vous ne pouvez ou ne devez pas reproduire, rendez l'incompatibilité explicite et modifiez le consommateur dans une version contrôlée. Un ORDER BY inexpliqué ajouté pendant la migration ne fait que remplacer une dépendance cachée par une autre.
Les mises à jour méritent une attention particulière. Quand un REWRITE modifie un champ de clé alternative, VSAM entretient l'index selon sa définition et son mode de mise à niveau. Dans Postgres, une colonne générée, un déclencheur ou le chemin d'écriture applicatif doit mettre à jour la valeur correspondante atomiquement avec l'enregistrement. Si un service écrit le champ analysé et qu'un autre importe les images brutes, centralisez la dérivation de clé dans une fonction testée. Deux implémentations finiront par diverger sur le remplissage ou les octets invalides.
Inventoriez aussi les chemins qui existent mais semblent inutilisés. Certains sont des outils de reprise ou des exports d'audit invoqués seulement après une panne. Marquez-les comme dormants avec des preuves. Ne les supprimez pas discrètement parce que trente jours de traces en ligne n'ont montré aucun appel.
L'état du parcours doit devenir une règle de curseur explicite
Un parcours VSAM possède un état du point de vue de l'appelant. Les requêtes SQL manipulent des ensembles. Le remplacement doit donc définir le positionnement et la continuation au lieu de dépendre de l'état de connexion ou d'une pagination par décalage.
START ou STARTBR peut demander une clé exacte, un préfixe générique ou la première clé supérieure ou égale aux octets fournis. Les appels suivants et précédents avancent par rapport à cette position. Les applications observent les limites: le démarrage renvoie-t-il un enregistrement, établit-il seulement une position, signale-t-il une absence ou place-t-il le parcours en fin de fichier? Votre adaptateur doit reproduire le contrat réellement utilisé par chaque appelant.
Utilisez une pagination par clé avec le tuple d'ordre historique complet. Pour un parcours avant sur (alternate_key, base_key), renvoyez les deux valeurs dans un curseur opaque et reprenez par une comparaison stricte:
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;
Pour un démarrage supérieur ou égal, utilisez >= seulement sur la demande initiale. Les continuations utilisent > afin de ne pas répéter la dernière ligne. Le parcours arrière inverse la comparaison et l'ordre. La pagination par décalage est mauvaise ici, car les insertions et suppressions avant le décalage déplacent la fenêtre, tandis qu'un grand décalage oblige Postgres à parcourir des lignes déjà consommées.
Les clés partielles exigent des bornes au niveau des octets, pas un LIKE 'ABC%' improvisé. Pour un préfixe binaire fixe, calculez une borne inférieure égale au préfixe complété par le suffixe minimal et une borne supérieure exclusive égale au préfixe suivant. Si aucun préfixe suivant n'existe parce que tous les octets sont maximaux, gardez seulement la borne inférieure et vérifiez le préfixe des clés renvoyées. Placez cette logique dans un adaptateur unique et testez les cas vide, tout zéro, tout maximum et avec espaces internes.
La concurrence impose un choix de politique. Un long parcours VSAM et une suite de requêtes SQL sans état peuvent voir différemment insertions et suppressions. Décidez si le remplacement maintient une transaction repeatable read, matérialise une liste de travail ou accepte une vue mouvante avec reprise par clé. Reproduisez le comportement source requis par le processus métier, pas une image théorique de VSAM. Garder une transaction ouverte pendant la session écran d'un opérateur est généralement un mauvais compromis, tandis que matérialiser des clés pour un batch borné fonctionne souvent bien.
Le batch nocturne transforme l'ordre en logique métier
Les programmes batch utilisent souvent l'entrée triée comme flux de contrôle. Le programme détecte une rupture de clé, vide les totaux, ouvre un nouveau groupe de rapport, reporte l'enregistrement précédent ou rapproche deux fichiers en avançant la clé la plus faible. Changez l'ordre et vous changez le calcul, même si chaque enregistrement est arrivé.
Une panne typique commence sans bruit. La migration exporte toutes les lignes depuis Postgres, les nombres et sommes de contrôle correspondent, et l'API en ligne réussit les tests de clé exacte. À 1 h 00, un job lit les polices via un chemin alternatif par agence. Les clés d'agence égales arrivent dans un autre ordre de clé de base. Le programme associe chaque police au prochain enregistrement de transaction par une fusion en un passage. Un enregistrement devient inférieur à la clé de transaction conservée, tombe dans une branche d'exception et empêche l'équilibrage du total de contrôle. La base est disponible, mais le batch est cassé.
Une autre panne vient de l'ordre implicite en SQL. Un développeur teste SELECT ... FROM policy WHERE status = 'A' et voit l'ordre de clé primaire parce que le plan choisi parcourt un index. Plus tard, les statistiques de production favorisent un parcours séquentiel. Les mêmes lignes arrivent dans l'ordre du tas. PostgreSQL a toujours indiqué que les lignes n'ont aucun ordre garanti sans ORDER BY. Le test a approuvé un plan par accident, pas un contrat.
Transformez chaque séquence consommée en produit de données explicite. Consignez le chemin source, le tuple de tri complet, l'encodage, la règle de départage des doublons et la limite du snapshot. La requête d'extraction doit tous les déclarer. Si le batch lit historiquement une génération figée créée par une étape amont, ne le pointez pas vers les tables actives en espérant que l'isolation donnera la même coupure. Créez une table de staging propre au run ou exportez sous un snapshot déclaré.
Un artefact de parité utile compare les flux ordonnés, pas seulement les hachages non ordonnés:
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>
Le format montre l'endroit où l'égalité s'arrête, ce dont un ingénieur a besoin la nuit. Produisez une empreinte sur la clé et les octets de l'enregistrement préfixés par leur longueur, pour empêcher les collisions de limites de champ. Conservez les nombres et totaux par groupe là où le batch emploie des ruptures de contrôle. Une somme de contrôle unique pour le fichier entier indique que quelque chose a changé, pas quel contrat d'accès a échoué.
Le comportement des écritures compte autant que la lecture
Les écritures doivent préserver l'immuabilité de la clé, le rejet des doublons, l'entretien des index et la conversion des statuts dans une seule transaction. Une migration peut copier les données correctement puis corrompre le parcours du lendemain si la première mise à jour en ligne suit d'autres règles.
Beaucoup d'applications KSDS ne modifient pas la clé primaire pendant un REWRITE; elles suppriment l'enregistrement et en écrivent un nouveau. Une API relationnelle peut autoriser sans réflexion UPDATE ... SET id = .... Décidez si la couche de compatibilité refuse les changements de clé ou met en oeuvre les conséquences historiques de suppression et création, y compris pour les index alternatifs et l'audit. Ne laissez pas un ORM choisir.
Convertissez les échecs attendus volontairement. Clé primaire dupliquée, clé alternative unique dupliquée, enregistrement absent, mise à jour périmée et fin de parcours sont des résultats applicatifs, pas des erreurs internes quelconques. Les valeurs SQLSTATE de Postgres sont utiles dans l'adaptateur, mais les exposer à des appelants hérités du COBOL change des branches qui pilotent parfois reprises ou messages opérateur. Construisez une petite table de correspondance et testez le statut exact renvoyé pour chaque opération.
Le verrouillage diffère aussi. Une transaction source peut lire pour mise à jour, modifier l'enregistrement et le réécrire dans une unité de travail. La cible a besoin d'une règle équivalente, souvent SELECT ... FOR UPDATE suivi d'une mise à jour avec contrôle de version. Pour des clients déconnectés, une colonne de version optimiste peut empêcher un écran ancien d'écraser un enregistrement récent. C'est une modernisation, mais elle doit produire le statut visible attendu par l'appelant historique jusqu'à sa modification.
La double écriture dans VSAM et Postgres est une recommandation de sécurité populaire, et je déconseille d'en faire le choix par défaut. Deux systèmes aux contraintes et ordres différents créent un troisième problème de réconciliation, surtout lorsqu'un échec partiel change une clé alternative d'un seul côté. Un journal de changements capturé, avec rejeu et retard mesuré, peut se justifier pour la bascule. Une double écriture sans échéance masque la responsabilité. Préférez un seul écrivain à une limite de bascule déclarée, avec un retour arrière répété qui restaure l'ancien écrivain et rejoue les changements acceptés.
Construisez la parité autour des opérations, séquences et échecs
Comparer les enregistrements est nécessaire et insuffisant. Le banc de parité doit lancer les opérations des applications, observer les séquences ordonnées et comparer le comportement des échecs.
Créez des fixtures désagréables pour les deux systèmes: octets de clé minimaux et maximaux, espaces de début et de fin, texte numérique avec zéros initiaux, clés alternatives dupliquées, champs facultatifs absents, encodages historiques invalides, clés voisines d'une limite de préfixe et enregistrements réécrits dont la clé alternative se déplace. Ajoutez ensuite un petit générateur aléatoire. La couverture aléatoire ne doit jamais remplacer des fixtures nommées qui expliquent un échec.
Pour chaque contrat d'accès, exécutez cette séquence:
- Chargez des images d'enregistrement identiques dans la fixture source et le modèle d'atterrissage cible.
- Exécutez les opérations exactes, supérieures ou égales, par préfixe, suivantes et précédentes déclarées valides par l'inventaire.
- Comparez octets de clé, octets d'enregistrement, statut, ordre et conditions de fin renvoyés.
- Appliquez écritures, réécritures, changements de clé alternative et suppressions, puis recommencez les lectures.
- Lancez le batch consommateur et comparez rapports, totaux de contrôle, rejets et données de reprise.
Traitez le trafic de production enregistré comme un autre jeu de fixtures après avoir retiré ou protégé les champs sensibles selon les règles du client. CodeHero vérifie le comportement réécrit par un banc de parité sur le trafic de production enregistré. Son analyse de toute la base de code aide ici, car le contrat traverse COBOL, JCL, utilitaires et copybooks au lieu de résider dans un dossier du dépôt. Cela ne remplace ni les limites synthétiques ni les runs batch complets.
Définissez l'acceptation par chemin. Une recherche exacte peut exiger sortie et statut identiques au niveau des octets. Un rapport modernisé peut autoriser une autre mise en forme tout en exigeant les mêmes groupes et totaux. Un défaut corrigé demande une différence approuvée, pas une exception cachée dans le comparateur. Stockez ces décisions avec le test afin qu'un nettoyage ultérieur du schéma n'efface pas une règle de compatibilité par accident.
Testez les performances avec les mêmes formes d'accès. Une requête qui renvoie la bonne première page après avoir parcouru toute la table échouera sous la charge batch. Examinez EXPLAIN (ANALYZE, BUFFERS) sur des volumes représentatifs, vérifiez que les index composites correspondent aux comparaisons et à l'ordre, et testez des clés alternatives déséquilibrées où une valeur possède beaucoup d'enregistrements. La correction passe d'abord, mais un parcours qui rate sa fenêtre nocturne est incorrect en exploitation.
L'état de reprise fait partie du contrat de données
Une bascule batch doit préserver l'endroit où le travail peut reprendre, pas seulement les lignes de la nouvelle base. Les anciens jobs enregistrent souvent un dernier identifiant, un nombre de lignes, un total de contrôle, un nom de génération ou un indicateur du planificateur dont le sens dépend de la séquence source. Si la cible change cette séquence, le même point de reprise peut sauter des lignes ou les traiter deux fois.
Commencez par suivre les données de reprise sur tout le flux de jobs. Un programme COBOL peut écrire la dernière agence et la dernière police terminées dans un petit fichier, tandis que les règles de disposition JCL déterminent si ce fichier survit à un abend. Une étape suivante peut ne supprimer ce point qu'après la copie des rapports et la validation des totaux. Déplacer les données principales vers Postgres sans reproduire ces limites de validation transforme une panne récupérable en relance incertaine.
Ne traduisez jamais une position d'enregistrement source en décalage Postgres. Les adresses relatives et positions d'intervalle de contrôle appartiennent à l'implémentation VSAM, et les décalages SQL deviennent instables lorsque les lignes changent. Convertissez l'état de reprise vers le tuple d'ordre logique complet, comme (branch_key_bytes, policy_key_bytes), plus l'identité du run batch et sa limite de snapshot. Reprenez avec une comparaison stricte après le dernier tuple validé. Si l'ancien programme relit volontairement l'enregistrement du point de contrôle et le détecte comme doublon, gardez cette règle dans l'adaptateur au lieu de remplacer silencieusement >= par >.
L'écriture du point de contrôle et les effets métier qu'elle protège ont besoin d'une même limite atomique. Quand un batch modifie directement Postgres, stockez si possible ses résultats, totaux et prochain curseur dans la même transaction. Quand il produit des fichiers pour des étapes suivantes, écrivez une sortie propre au run et ne la publiez qu'après la validation en base. Avancer le curseur avant que le fichier atteigne sa place finale crée un trou; publier le fichier avant de valider le curseur crée un doublon à la reprise.
Testez les interruptions au lieu de seulement en parler. Tuez le processus cible après la première ligne, au milieu d'un groupe de clés alternatives dupliquées, juste avant un total de groupe, après la validation en base mais avant la publication de la sortie, et pendant le nettoyage final du point de contrôle. Redémarrez depuis l'état capturé et comparez les artefacts finaux à un run source ininterrompu. Le travail intermédiaire n'a pas toujours besoin d'être identique octet par octet, mais enregistrements acceptés, rejets, totaux et sorties publiées doivent respecter le contrat déclaré.
Le retour arrière de bascule exige la même discipline. Enregistrez une limite haute des changements acceptés, arrêtez ou bloquez les écrivains, laissez finir le travail engagé, puis prouvez quel système possède les écritures avant l'ouverture de la fenêtre batch. Si le retour redonne cette responsabilité à VSAM, rejouez uniquement les changements après sa limite haute confirmée et vérifiez ensuite les chemins alternatifs. Une consigne vague de renvoi du trafic ne couvre ni transactions en file, ni exports partiellement publiés, ni points de reprise créés selon l'ordre cible.
Donnez aux opérations un runbook avec des preuves concrètes: propriétaire des écritures, limites hautes source et cible, identifiants des runs actifs, dernier tuple d'ordre validé, statut de publication des sorties, et commande ou requête qui vérifie chaque valeur. Répétez-le avec les mêmes dépendances de planification qu'en production. Le pire moment pour découvrir qu'un fichier de reprise contient une clé texte tronquée est après le premier abend côté cible.
Modernisez seulement après avoir tenu la limite de compatibilité
Le premier modèle Postgres sûr peut être moins élégant que le dernier. Clés brutes, images d'enregistrement, index de compatibilité explicites et adaptateurs conservent les preuves pendant que vous validez le comportement. Une fois la parité tenue, modernisez derrière cette limite par changements mesurés.
Une cible utile comprend souvent trois couches. La couche d'atterrissage conserve sans perte les octets importés et les métadonnées source. La couche de compatibilité met en oeuvre lectures, parcours, statuts et exports ordonnés historiques. La couche de domaine expose des tables relationnelles typées et des API au nouveau code. Elles peuvent partager une base, mais leurs contrats diffèrent. Les nouveaux services ne doivent pas analyser les octets bruts des copybooks, et les anciens appelants ne doivent pas accéder directement aux tables dont les clés évoluent encore.
Choisissez la clé primaire durable selon la propriété. Si la clé historique est stable, compacte et identifie vraiment l'entité, la conserver peut être raisonnable. Si elle incorpore des attributs modifiables, des codes de type surchargés ou du remplissage de présentation, utilisez une clé de substitution et gardez l'ancienne sous contrainte unique. Les clés étrangères doivent pointer vers l'identité qui reste stable lorsque le métier corrige un code. C'est une décision de modèle, pas une règle générale où les clés naturelles ou de substitution gagneraient toujours.
Retirez la compatibilité une dépendance à la fois. Passez un consommateur à une API de domaine dont l'ordre est documenté, soumettez les deux chemins à la parité, puis retirez son ancien chemin de l'inventaire. Songez à supprimer les index de clés brutes ou les images d'enregistrement seulement lorsqu'aucun appelant n'a plus besoin de l'ordre binaire. Le stockage coûte peu par rapport à la reconstitution de la raison pour laquelle un job de fin d'année triait autrefois 9 avant A.
Le plan de migration doit traiter le batch nocturne comme un consommateur à part entière avec un responsable, une fenêtre de test, une procédure de reprise et une limite de retour arrière. S'il dit seulement que le KSDS devient une table, il ne décrit pas le travail. Un plan digne de confiance nomme les contrats d'octets conservés, les comportements volontairement changés et le test qui prouve chaque décision avant que l'ancien cluster cesse d'être le système de référence.
FAQ
Une clé KSDS VSAM peut-elle devenir directement une clé primaire Postgres?
Parfois, mais seulement après réussite des tests de parité sur l'égalité binaire, l'unicité, l'ordre et les règles de mise à jour. Gardez les octets d'origine pendant la migration, même si vous créez aussi une identité typée plus propre.
Pourquoi l'ordre EBCDIC compte-t-il encore après conversion en UTF-8?
La logique batch et de parcours peut observer l'ancienne séquence d'octets, tandis que le texte Postgres utilise un classement sur les caractères décodés. Les mêmes valeurs visibles peuvent donc arriver dans un autre ordre et déclencher d'autres ruptures de contrôle.
Comment stocker les clés alternatives VSAM dupliquées dans Postgres?
Utilisez un index non unique dont les colonnes comprennent la clé alternative et un départage prouvé sur le chemin source. Interrogez avec un ORDER BY sur le tuple complet; un index sur la seule valeur alternative ne définit pas l'ordre des doublons.
Faire correspondre nombres de lignes et sommes de contrôle suffit-il?
Non. Ces contrôles manquent l'ordre, le positionnement, les statuts, les clés partielles et l'entretien des index après mise à jour. Comparez les résultats ordonnés des opérations et lancez le vrai batch consommateur.
Qu'est-ce qui remplace STARTBR et READNEXT dans Postgres?
Un adaptateur de compatibilité les traduit généralement en requêtes par clé sur le tuple d'ordre historique complet. La requête initiale établit une position exacte ou supérieure ou égale, puis les suivantes reprennent strictement après le dernier tuple renvoyé.
Une migration doit-elle retirer les espaces des clés VSAM?
Pas dans la représentation sans perte. Vous pouvez ajouter des colonnes normalisées pour le métier, mais supprimer le remplissage avant la parité peut fusionner des clés binaires distinctes et changer les limites de tri.
Postgres peut-il renvoyer l'ordre de clé primaire sans ORDER BY?
Cela peut sembler vrai pendant un test, mais SQL ne garantit pas cet ordre. Un changement de plan, un vacuum ou une réécriture de table peut produire une autre séquence. Chaque consommateur sensible à l'ordre exige un ORDER BY explicite.
Faut-il écrire à la fois dans VSAM et Postgres pendant la bascule?
Seulement avec un dispositif de réconciliation défini et une transition de responsabilité courte. Pour la plupart des parcs, un seul écrivain déclaré, une capture des changements, leur rejeu et un retour arrière répété créent moins de pannes ambiguës.
Comment tester le parcours VSAM avec des clés partielles?
Construisez des bornes inférieure et supérieure en octets, puis comparez les cas limites à la source. Incluez préfixes vides, espaces, octets zéro et maximaux, absences de résultat et doublons aux deux extrémités.
Quand peut-on supprimer l'image brute d'un enregistrement VSAM?
Seulement après que tous les appelants ont quitté le chemin de compatibilité et que les tests conservés prouvent la couverture du modèle typé. Jusque-là, l'image brute reste la preuve qui permet de diagnostiquer les erreurs de conversion et de parité.