Ir para o conteúdo
14 de ago. de 2026·8 min de leitura

Como migrar VSAM para Postgres quebra contratos ocultos de chave

Migrar VSAM para Postgres com segurança exige preservar bytes KSDS, índices alternativos, ordem de leitura e comportamento dos lotes.

Como migrar VSAM para Postgres quebra contratos ocultos de chave

Uma chave KSDS do VSAM e uma chave primária do Postgres podem identificar o mesmo registro de negócio e ainda impor contratos diferentes. Trate as duas como equivalentes e as telas on-line talvez pareçam corretas, até o momento em que um programa noturno percorre registros em uma ordem que ninguém documentou, um índice alternativo devolve duplicatas de outro jeito ou uma chave regravada muda qual registro vem depois.

Mover os bytes é a parte fácil. A migração só funciona quando você descobre todos os caminhos de acesso e reproduz o comportamento observável deles antes de melhorar o esquema. Isso inclui detalhes incômodos: preenchimento de largura fixa, ordenação EBCDIC, início por chave parcial, chaves alternativas duplicadas, atualizações que mantêm vários índices e comportamento de fim de arquivo depois de mudanças simultâneas. Já vi equipes testarem operações CRUD e declararem vitória enquanto o ambiente de lotes ainda dependia da personalidade física do KSDS.

Uma chave KSDS é um contrato de acesso, não uma coluna

Uma chave primária do Postgres expressa unicidade e identidade da linha dentro de uma tabela relacional. Uma chave primária KSDS também controla a posição na sequência lógica, o acesso por chave, o posicionamento de percurso e os estados esperados pelo código da aplicação. Essas funções se sobrepõem, mas não são iguais.

Em um KSDS, a chave é um campo fixo em um deslocamento e comprimento de bytes declarados dentro de cada registro. O VSAM compara esse campo conforme os dados e o ambiente apresentados. Os programas costumam montar a chave na working storage, preenchê-la, mover valores de exibição ou compactados para ela e passá-la por operações de arquivo COBOL ou comandos CICS. Os bytes fazem parte da interface, mesmo quando um copybook lhes dá um nome de negócio amigável.

Uma PRIMARY KEY do Postgres exige que todos os valores sejam únicos e não nulos, e o Postgres a sustenta com um índice B-tree único. Isso não diz se '00123 ' equivale a '00123', se bytes em EBCDIC são ordenados como texto UTF-8 nem se uma chamada pode iniciar um percurso apenas com a parte inicial de uma chave de negócio composta. Portanto, uma definição relacional limpa pode estar errada para a aplicação migrada.

Mantenha três identidades separadas durante a análise. A chave do registro é a sequência exata de bytes legados. A identidade de negócio é o que a organização diz que o registro significa, como conta mais data de vigência. A identidade do banco é a chave escolhida para referências e atualizações no Postgres. Às vezes as três podem convergir. Não force esse resultado antes que as evidências permitam.

A documentação da IBM sobre conjuntos de dados sequenciados por chave descreve registros ordenados pelo campo de chave e acessados direta ou sequencialmente. A documentação do PostgreSQL descreve a chave primária como uma restrição de unicidade e não nulidade que também cria um índice. Lidos em conjunto, os manuais expõem a lacuna: o VSAM documenta comportamento de acesso em torno de um registro; o Postgres documenta uma restrição relacional em torno de um valor. Seu projeto de compatibilidade precisa cobrir o comportamento ausente.

Inventarie as chamadas, não apenas o catálogo do cluster

O catálogo mostra quais clusters base, índices alternativos e caminhos existem. Ele não mostra quais programas dependem deles, quais formatos de chave esses programas montam nem o que fazem depois de um início malsucedido. Monte o inventário a partir do código, JCL, definições de transação, copybooks e observações de produção.

Procure no COBOL por READ, START, READ NEXT, READ PREVIOUS, REWRITE e DELETE para cada descrição de arquivo. Procure no código CICS por READ, STARTBR, READNEXT, READPREV, RESETBR, ENDBR, WRITE, REWRITE e DELETE, depois registre DATASET, RIDFLD, KEYLENGTH, GENERIC, GTEQ e os tokens de percurso. Encontre passos JCL que usem IDCAMS, SORT ou utilitários para copiar, descarregar, mesclar e validar o cluster. Inclua Assembler, PL/I, REXX e scripts do agendador caso toquem os mesmos dados.

Para cada operação, registre cinco itens:

  • O caminho usado: cluster base ou caminho nomeado de índice alternativo.
  • Os bytes exatos da chave e o comprimento declarado ou fornecido.
  • A operação e a regra de posição, inclusive exata, maior ou igual, próxima e anterior.
  • O formato esperado do resultado, o estado e o comportamento de duplicatas.
  • O consumidor posterior, em especial um passo de lote ou uma extração.

Não agrupe várias chamadas em uma linha só porque citam o mesmo arquivo. Uma consulta CICS que lê um número exato de cliente e uma tarefa COBOL noturna que começa em um prefixo de filial exercem contratos diferentes. A segunda também pode depender da sequência de duplicatas sob uma chave alternativa, mesmo que ninguém tenha pretendido tornar pública essa sequência.

O tráfego de produção gravado ajuda com comandos on-line, mas não captura comportamento agendado nem ramificações raras de recuperação. Combine-o com descoberta estática de chamadas e pelo menos um ciclo completo de lotes. Se o fechamento mensal usa outro caminho JCL, capture-o também. O objetivo é uma tabela finita de contratos de acesso capaz de conduzir testes, não um documento de arquitetura em prosa que cada pessoa interpreta de um jeito.

A igualdade de bytes e a de texto divergem rapidamente

Preserve os bytes originais da chave até provar que o valor decodificado tem o mesmo comportamento de igualdade e ordenação. Converter caracteres é uma mudança semântica, não uma limpeza.

Considere uma chave de cliente com dez bytes, formada por um código de região em maiúsculas, um número preenchido com zeros e espaços finais. Um carregador poderia decodificar EBCDIC, remover espaços, converter o número e armazenar (region text, customer_no integer). A nova representação parece melhor. Ela também pode descartar diferenças que o programa antigo produz, alterar comparações de valores malformados e perder os bytes exatos necessários para explicar uma falha de paridade.

A colação acrescenta outra armadilha. A ordem de texto no Postgres segue a colação escolhida para o banco ou a coluna, enquanto um percurso legado observa a ordem produzida pelos bytes codificados da chave e pelo ambiente VSAM. Letras, números, espaços, sinais, letras minúsculas que passaram pela validação e caracteres nacionais podem aparecer em outra posição. ORDER BY key_text não é uma alegação de compatibilidade até que os testes a comprovem com chaves representativas e adversas.

Uma tabela de aterrissagem conservadora mantém a identidade bruta ao lado dos campos interpretados:

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;

A chave bruta oferece busca sem perdas e uma referência estável para diagnóstico. As colunas interpretadas sustentam o modelo desejado. O índice único parcial testa uma hipótese de negócio sem fingir que todos os registros históricos estão limpos. Se a hipótese falhar na carga, você encontrou dados que pedem uma regra explícita, não um incômodo a esconder com ON CONFLICT DO NOTHING.

Para uma chave bruta compatível com texto, você pode usar uma função fixa de normalização e uma colação binária, mas documente cada transformação e teste a operação inversa. Para dados mistos ou zonados, bytea costuma ser a primeira representação honesta. Você pode removê-la mais tarde, depois que os testes de paridade provarem que nenhuma chamada observa a diferença. Remover a evidência antes da paridade inverte a ordem do trabalho.

Índices alternativos carregam semântica própria

Um índice alternativo não é apenas um índice secundário do Postgres. Ele é outro caminho de acesso, com extração de chave, regra de unicidade, tratamento de duplicatas e ordem de percurso próprios, exposto aos programas por um caminho.

O IDCAMS pode definir um índice alternativo com chaves únicas ou não únicas. Com chaves alternativas não únicas, vários registros base compartilham o mesmo valor alternativo. Uma chamada pode se posicionar nesse valor e percorrer os registros correspondentes. Um índice simples do Postgres em surname acelera a busca, mas não define uma ordem determinística entre sobrenomes iguais. O planejador pode devolver empates em outra ordem depois de vacuum, reconstrução do índice, mudança de plano ou movimentação de dados. SQL não promete ordem sem um ORDER BY que resolva os empates.

Modele explicitamente cada caminho alternativo. Suponha que a aplicação legada percorra apólices por código do agente e que, dentro de cada agente, tenha observado historicamente a ordem da chave base. Codifique as duas partes no índice e na consulta de compatibilidade:

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;

Não presuma a ordem secundária. Meça-a contra o caminho de origem, inclusive grupos duplicados criados em sequências diferentes e registros cuja chave alternativa mudou depois da criação. Se a ordem observada depende de um detalhe interno do VSAM que você não pode ou não deve reproduzir, declare a incompatibilidade e altere o consumidor em uma versão controlada. Um ORDER BY sem explicação adicionado durante a migração apenas substitui uma dependência oculta por outra.

As atualizações merecem atenção especial. Um REWRITE que muda um campo da chave alternativa faz o VSAM manter o índice conforme sua definição e configuração de atualização. No Postgres, uma coluna gerada, um trigger ou o caminho de escrita da aplicação deve atualizar o valor correspondente atomicamente junto com o registro. Se um serviço escreve o campo interpretado e outro importa imagens brutas, centralize a derivação da chave em uma função testada. Duas implementações acabarão divergindo no preenchimento ou em bytes inválidos.

Inventarie também caminhos que existem, mas parecem sem uso. Alguns são ferramentas de recuperação ou extrações de auditoria acionadas apenas depois de uma falha. Marque-os como inativos com evidências; não os remova em silêncio porque trinta dias de rastros on-line não mostraram chamadas.

O estado do percurso precisa virar uma regra explícita de cursor

Leia todo o ambiente de lotes
A plataforma analisa juntas todas as linguagens do código e suas dependências noturnas.

Do ponto de vista da chamada, um percurso VSAM mantém estado. Consultas SQL trabalham com conjuntos, então a substituição precisa definir posicionamento e continuação em vez de depender do estado da conexão ou de paginação por deslocamento.

START ou STARTBR pode solicitar uma chave exata, um prefixo genérico ou a primeira chave maior ou igual aos bytes fornecidos. As chamadas seguintes e anteriores avançam em relação a essa posição. As aplicações dependem do comportamento nas fronteiras: se o início devolve um registro, apenas define posição, informa que não encontrou ou coloca o percurso no fim do arquivo. O adaptador deve reproduzir o contrato que cada chamada realmente usa.

Use paginação por chave com a tupla completa da ordenação legada. Para um percurso à frente em (alternate_key, base_key), devolva os dois valores em um cursor opaco e retome com uma comparação estrita:

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;

Para um início maior ou igual, use >= apenas na solicitação inicial. As continuações usam > para que a última linha não se repita. O percurso inverso troca tanto a comparação quanto a ordem. Paginação por deslocamento está errada aqui, pois inserções e exclusões anteriores deslocam a janela, e um deslocamento grande obriga o Postgres a percorrer linhas que a aplicação já consumiu.

Chaves parciais precisam de limites no nível dos bytes, não de um LIKE 'ABC%' casual. Para um prefixo binário fixo, calcule um limite inferior igual ao prefixo preenchido com o sufixo mínimo e um limite superior exclusivo igual ao próximo prefixo possível. Se não houver prefixo seguinte porque todos os bytes são máximos, use apenas o limite inferior e verifique o prefixo nas chaves devolvidas. Coloque essa lógica em um único adaptador e teste casos vazios, só com zeros, máximos e com espaços internos.

A concorrência obriga uma escolha de política. Um percurso VSAM longo e uma sequência de solicitações SQL sem estado podem enxergar inserções ou exclusões de forma diferente. Decida se a substituição mantém uma transação repeatable read, materializa uma lista de trabalho ou aceita uma visão móvel com continuação por chave. Iguale o comportamento de origem exigido pelo processo de negócio, não uma imagem teórica do VSAM. Manter uma transação aberta durante a sessão de tela de uma pessoa geralmente é uma troca ruim; materializar chaves para um lote limitado costuma funcionar bem.

No lote noturno, a ordem vira lógica de negócio

Programas em lote frequentemente usam a entrada ordenada como fluxo de controle. O programa detecta uma quebra de chave, descarrega totais, abre outro grupo de relatório, carrega o registro anterior ou combina dois arquivos avançando a chave menor. Mude a ordem e você muda o cálculo, mesmo que todos os registros tenham chegado.

Uma falha típica começa de modo inocente. A migração exporta todas as linhas do Postgres, contagens e checksums conferem, e a API on-line passa nos testes de chave exata. À 1h, uma tarefa lê apólices por filial em um caminho alternativo. Chaves iguais de filial chegam em outra ordem de chave base. O programa associa cada apólice ao próximo registro de transação com uma mesclagem de passagem única. Um registro agora é menor que a chave de transação guardada, cai em uma ramificação de exceção e impede que o total de controle feche. O banco está disponível, mas o lote continua quebrado.

Outra falha vem da ordem implícita no SQL. Uma pessoa testa SELECT ... FROM policy WHERE status = 'A' e vê a ordem da chave primária porque o plano escolhido percorre um índice. Depois, as estatísticas de produção favorecem uma varredura sequencial. As mesmas linhas chegam na ordem física. O PostgreSQL sempre deixou claro que linhas não têm ordem garantida sem ORDER BY; o teste aprovou por acidente um plano, não um contrato.

Transforme cada sequência consumida em um produto de dados explícito. Registre caminho de origem, tupla completa de ordenação, codificação, regra de desempate e limite do snapshot. A consulta de extração deve declarar todos eles. Se historicamente o lote lê uma geração congelada criada por uma etapa anterior, não o aponte para tabelas ativas esperando que o isolamento produza o mesmo corte. Crie uma tabela de staging para a execução ou exporte sob um snapshot declarado.

Um artefato de paridade útil compara fluxos ordenados, não apenas hashes sem ordem:

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>

O formato mostra onde a igualdade terminou, que é o que uma pessoa de engenharia precisa de madrugada. Gere um resumo sobre bytes de chave e registro prefixados pelo comprimento, para que limites de campo não colidam. Mantenha contagens e totais por grupo onde o lote usa quebras de controle. Um único checksum do arquivo inteiro diz que algo mudou; não diz qual contrato de acesso falhou.

O comportamento de escrita importa tanto quanto o de leitura

Faça o lote noturno comprovar
A paridade com tráfego gravado revela o que um esquema limpo pode perder.

As escritas precisam preservar imutabilidade de chave, rejeição de duplicatas, manutenção dos índices e mapeamento de estados em uma só transação. Uma migração pode copiar os dados corretamente e ainda corromper o percurso de amanhã se a primeira atualização on-line seguir regras diferentes.

Muitas aplicações KSDS não alteram a chave primária durante um REWRITE; elas excluem o registro e gravam outro. Uma API relacional pode permitir sem cuidado UPDATE ... SET id = .... Decida se a camada de compatibilidade rejeita mudanças de chave ou implementa as consequências legadas de excluir e criar, incluindo índices alternativos e auditoria. Não deixe um ORM decidir.

Mapeie de propósito as falhas esperadas. Chave primária duplicada, chave alternativa única duplicada, registro ausente, atualização obsoleta e fim do percurso são resultados da aplicação, não erros internos genéricos. Os valores SQLSTATE do Postgres ajudam dentro do adaptador, mas expô-los a chamadas da época do COBOL muda ramificações que podem controlar novas tentativas ou mensagens de operação. Crie uma pequena tabela de mapeamento e teste o estado exato de cada operação.

O bloqueio também difere. Uma transação de origem pode ler para atualizar, modificar o registro e regravá-lo dentro de uma unidade de trabalho. O destino precisa de uma regra equivalente, geralmente SELECT ... FOR UPDATE seguido de atualização com verificação de versão. Para clientes desconectados, uma coluna de versão otimista pode impedir que uma tela antiga sobrescreva um registro mais novo. Isso é uma modernização, mas precisa gerar o estado visível esperado pela chamada legada até que ela mude.

A escrita dupla no VSAM e no Postgres é uma recomendação de segurança popular, e não recomendo torná-la padrão. Dois sistemas com restrições e ordens diferentes criam um terceiro problema de conciliação, principalmente quando uma falha parcial muda uma chave alternativa em apenas um lado. Um log de mudanças capturado, com reprodução e atraso medido, pode ser justificável no corte. Um período aberto de escrita dupla esconde a responsabilidade. Prefira um escritor em uma fronteira declarada, com reversão ensaiada que restaure o escritor anterior e reproduza as mudanças aceitas.

Construa a paridade em torno de operações, sequências e falhas

A comparação por registro é necessária, mas insuficiente. O mecanismo de paridade precisa executar as operações das aplicações, observar sequências ordenadas e comparar o comportamento das falhas.

Crie dados de teste desagradáveis para ambos os sistemas: bytes mínimos e máximos de chave, espaços iniciais e finais, texto numérico com zeros iniciais, chaves alternativas duplicadas, campos opcionais ausentes, codificações históricas inválidas, chaves ao lado de um limite de prefixo e registros regravados cuja chave alternativa se move. Acrescente depois um pequeno gerador aleatório. Cobertura aleatória nunca deve substituir casos nomeados que explicam uma falha.

Para cada contrato de acesso, execute esta sequência:

  1. Carregue imagens de registro idênticas no teste de origem e no modelo de aterrissagem do destino.
  2. Execute as operações exatas, maior ou igual, por prefixo, seguinte e anterior que o inventário considera válidas.
  3. Compare os bytes de chave, bytes de registro, estado, ordem e condições de fim devolvidos.
  4. Aplique escritas, regravações, mudanças de chave alternativa e exclusões; depois repita as leituras.
  5. Execute o lote consumidor e compare relatórios, totais de controle, rejeições e dados de reinício.

Trate o tráfego de produção gravado como outro conjunto de teste, depois de remover ou proteger campos sensíveis conforme as regras do cliente. A CodeHero verifica o comportamento reescrito com um mecanismo de paridade contra tráfego de produção gravado, e a análise do código inteiro ajuda porque o contrato atravessa COBOL, JCL, utilitários e copybooks em vez de viver em uma pasta. Isso não elimina a necessidade de casos sintéticos de limite nem de execuções completas dos lotes.

Defina a aceitação por caminho. Uma busca exata pode exigir saída e estado idênticos em bytes. Um relatório modernizado pode permitir mudanças de formato, mas exigir os mesmos grupos e totais. Um defeito corrigido precisa de uma diferença aprovada, não de uma exceção oculta no comparador. Guarde essas decisões junto ao teste para que uma limpeza posterior do esquema não apague por acidente uma regra de compatibilidade.

Faça testes de desempenho com os mesmos formatos de acesso. Uma consulta que devolve a primeira página correta depois de percorrer a tabela inteira falhará sob carga de lote. Examine EXPLAIN (ANALYZE, BUFFERS) com tamanhos representativos, confira se índices compostos correspondem às comparações e à ordem, e teste chaves alternativas desequilibradas nas quais um valor possui muitos registros. A correção vem primeiro, mas um percurso que perde a janela noturna está errado na operação.

O estado de reinício faz parte do contrato dos dados

Preserve o comportamento das chaves KSDS
A CodeHero mantém o comportamento observado ao reescrever COBOL e JCL sobre Postgres.

Um corte de lote precisa preservar de onde o trabalho pode ser retomado, não apenas quais linhas estão no banco novo. Tarefas legadas costumam guardar a última chave, uma contagem, um total de controle, um nome de geração ou um sinal do agendador cujo significado depende da sequência de origem. Se o destino muda essa sequência, o mesmo ponto de controle pode pular linhas ou processá-las duas vezes.

Comece rastreando os dados de reinício por todo o fluxo. Um programa COBOL pode gravar a última filial e apólice concluídas em um arquivo pequeno, enquanto regras de disposição JCL decidem se esse arquivo sobrevive a um abend. Uma etapa posterior talvez apague o ponto só depois de copiar relatórios e validar totais. Mover os dados principais para Postgres sem reproduzir essas fronteiras de confirmação transforma uma falha recuperável em uma repetição incerta.

Nunca traduza uma posição de registro de origem em deslocamento do Postgres. Endereços relativos de bytes e posições de intervalo de controle pertencem à implementação do VSAM, e deslocamentos SQL ficam instáveis quando as linhas mudam. Converta o estado de reinício para a tupla lógica completa, como (branch_key_bytes, policy_key_bytes), somada à identidade da execução e ao limite do snapshot. Retome com comparação estrita depois da última tupla confirmada. Se o programa antigo relê de propósito o registro do ponto e o detecta como duplicado, preserve essa regra no adaptador em vez de trocar >= por > em silêncio.

A gravação do ponto de controle e os efeitos de negócio que ele protege precisam de uma fronteira atômica. Quando um lote atualiza o Postgres diretamente, guarde suas linhas de resultado, totais e próximo cursor na mesma transação quando for viável. Quando ele produz arquivos para etapas posteriores, grave saídas ligadas à execução e publique-as apenas depois da confirmação no banco. Avançar o cursor antes de o arquivo chegar ao local final cria uma lacuna; publicar a saída antes de confirmar o cursor cria duplicata no reinício.

Teste a interrupção em vez de apenas discuti-la. Encerre o processo de destino depois da primeira linha, no meio de um grupo de chaves alternativas duplicadas, imediatamente antes de um total de grupo, depois da confirmação no banco mas antes da publicação da saída e durante a limpeza final do ponto. Reinicie a partir do estado capturado e compare os artefatos finais com uma execução de origem sem interrupção. O trabalho intermediário nem sempre precisa ser idêntico byte a byte, mas registros aceitos, rejeições, totais e saída publicada precisam respeitar o contrato declarado.

A reversão do corte exige a mesma disciplina. Registre uma marca máxima para mudanças aceitas, pare ou bloqueie os escritores, deixe o trabalho em andamento terminar e prove qual sistema controla as escritas antes da abertura da janela do lote. Se a reversão devolve o controle ao VSAM, reproduza apenas mudanças depois da marca confirmada e verifique em seguida os caminhos alternativos. Uma instrução vaga para devolver o tráfego não cobre transações em fila, extrações parcialmente publicadas nem pontos criados contra a ordem do destino.

Entregue à operação um manual com evidências concretas: controle das escritas, marcas máximas de origem e destino, identificadores das execuções ativas, última tupla confirmada, estado de publicação das saídas e comando ou consulta que verifica cada valor. Ensaie com as mesmas dependências do agendador usadas em produção. O pior momento para descobrir que um arquivo de reinício contém uma chave de texto aparada é depois do primeiro abend no destino.

Modernize somente depois de firmar a fronteira de compatibilidade

O primeiro modelo seguro no Postgres pode parecer menos elegante que o final. Chaves brutas, imagens dos registros, índices explícitos de compatibilidade e adaptadores preservam evidências enquanto você comprova o comportamento. Quando a paridade estiver firme, modernize atrás dessa fronteira em mudanças mensuradas.

Um bom destino costuma ter três camadas. A camada de aterrissagem guarda sem perdas os bytes importados e metadados de origem. A camada de compatibilidade implementa leituras, percursos, estados e extrações ordenadas legadas. A camada de domínio expõe tabelas relacionais tipadas e APIs ao código novo. Elas podem compartilhar um banco, mas têm contratos diferentes. Serviços novos não devem interpretar bytes brutos de copybooks, e chamadas antigas não devem acessar diretamente tabelas cujas chaves ainda mudam.

Escolha a chave primária duradoura conforme a propriedade. Se a chave legada for estável, compacta e realmente identificar a entidade, mantê-la pode fazer sentido. Se ela embutir atributos mutáveis, códigos de tipo sobrecarregados ou preenchimento de apresentação, use uma chave substituta e preserve a legada sob uma restrição única. Chaves estrangeiras devem apontar para a identidade que fica estável quando o negócio corrige um código. Essa é uma decisão do modelo de dados, não uma regra geral em que chaves naturais ou substitutas sempre vencem.

Retire a compatibilidade uma dependência por vez. Mude um consumidor para uma API de domínio com ordenação documentada, passe os dois caminhos pela paridade e remova do inventário o caminho legado dele. Só depois que nenhuma chamada precisar da ordem de bytes considere apagar índices de chave bruta ou imagens dos registros. Armazenamento custa pouco perto de reconstruir por que uma tarefa de fim de ano um dia ordenou 9 antes de A.

O plano de migração deve nomear o lote noturno como consumidor de primeira classe, com responsável, janela de teste, procedimento de reinício e fronteira de reversão. Se ele diz apenas que o KSDS vira uma tabela, não descreveu o trabalho. Um plano confiável indica quais contratos de bytes permanecem, quais comportamentos mudam por decisão e qual teste comprova cada escolha antes de o cluster antigo deixar de ser o sistema oficial.

Perguntas frequentes

Uma chave KSDS do VSAM pode virar diretamente a chave primária do Postgres?

Às vezes, mas apenas depois que igualdade de bytes, unicidade, ordem e regras de atualização passarem nos testes de paridade. Preserve os bytes originais durante a migração mesmo que também crie uma identidade tipada mais limpa.

Por que a ordem EBCDIC importa depois da conversão para UTF-8?

A lógica de lote e percurso pode observar a sequência antiga de bytes, enquanto o texto do Postgres usa uma colação sobre caracteres decodificados. Os mesmos valores visíveis podem chegar em outra ordem e disparar quebras de controle diferentes.

Como guardar chaves alternativas VSAM duplicadas no Postgres?

Use um índice não único cujas colunas incluam a chave alternativa e um desempate comprovado contra a origem. Consulte com ORDER BY sobre a tupla completa; um índice apenas no valor alternativo não define a ordem das duplicatas.

Igualar contagens e checksums basta para uma migração VSAM?

Não. Essas verificações deixam passar ordem, posicionamento, estados, comportamento de chave parcial e manutenção de índices após mudanças. Compare resultados ordenados das operações e execute o lote real que consome os dados.

O que substitui STARTBR e READNEXT no Postgres?

Um adaptador de compatibilidade normalmente os converte em consultas por chave sobre a tupla completa da ordem legada. A consulta inicial estabelece posição exata ou maior ou igual, e as posteriores retomam estritamente depois da última tupla.

A migração deve remover espaços das chaves VSAM?

Não na representação sem perdas. Você pode adicionar colunas normalizadas para uso do negócio, mas remover o preenchimento antes da paridade pode unir chaves de bytes distintas e mudar limites de ordenação.

O Postgres pode devolver linhas na ordem da chave primária sem ORDER BY?

Pode parecer assim em um teste, mas SQL não garante essa ordem. Mudanças de plano, vacuum ou regravações de tabela podem produzir outra sequência. Todo consumidor dependente da ordem precisa de um ORDER BY explícito.

Vale escrever no VSAM e no Postgres ao mesmo tempo durante o corte?

Somente com projeto definido de conciliação e uma transição curta de controle. Para a maioria dos ambientes, um escritor declarado, captura das mudanças, reprodução e reversão ensaiada criam menos falhas ambíguas.

Como testar um percurso VSAM com chaves parciais?

Monte limites inferior e superior no nível dos bytes e compare casos de fronteira com a origem. Inclua prefixos vazios, espaços, zeros, bytes máximos, resultados ausentes e duplicatas nos dois extremos.

Quando a imagem bruta do registro VSAM pode ser apagada?

Somente depois que todas as chamadas saírem do caminho de compatibilidade e os testes preservados comprovarem que o modelo tipado cobre o comportamento necessário. Até lá, a imagem bruta é a evidência para diagnosticar erros de conversão e paridade.