Translate

Mostrar mensagens com a etiqueta commit. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta commit. Mostrar todas as mensagens

segunda-feira, 4 de maio de 2026

🔥☕ O SUBMUNDO DO Db2 z/OS — LOGS, RECOVERY E O QUE ACONTECE QUANDO O BANCO “MORRE” ☕🔥

 

Bellacosa Mainframe em uma visão sobre o LOG do DB2

🔥☕ O SUBMUNDO DO Db2 z/OS — LOGS, RECOVERY E O QUE ACONTECE QUANDO O BANCO “MORRE” ☕🔥

Existe um momento na vida de todo programador COBOL/Db2 em que ele descobre uma verdade assustadora:

O Db2 nunca esquece nada.

Cada:

  • INSERT,
  • UPDATE,
  • DELETE,
  • COMMIT,
  • ROLLBACK,
  • ALTER,
  • REORG,

deixa rastros.

E esses rastros vivem dentro de uma das estruturas mais importantes do ecossistema mainframe:

🔥 O LOG DO Db2.

Se você é programador COBOL pleno e acha que recovery é “coisa de DBA”, cuidado.

Porque no dia em que um:

-904
-911
-803
00C90084
RESOURCE UNAVAILABLE

explodir produção às 3h da manhã…

você vai descobrir que entender o log do Db2 muda completamente sua carreira.


☕ O QUE É O LOG DO Db2?

O log do Db2 é o “diário transacional” do banco.

Tudo que altera dados gera registros de log.

O Db2 escreve:

  • before image,
  • after image,
  • controle transacional,
  • checkpoints,
  • unidades de recuperação.

Basicamente:

ALTERAÇÃO → LOG → DISCO

Antes mesmo da página ser gravada no tablespace.


🔥 ACTIVE LOGS vs ARCHIVE LOGS

Aqui começa uma das maiores confusões dos iniciantes.

🔹 Active Logs

São os logs online e ativos.

Ficam sendo usados continuamente.

Eles armazenam:

  • alterações recentes,
  • transações em andamento,
  • recovery imediato.

São críticos.

Perder active log é pesadelo nível apocalipse.


🔹 Archive Logs

Quando active logs ficam cheios:

  • Db2 descarrega,
  • copia,
  • arquiva.

Esses logs históricos viram:

ARCHIVE LOGS

Eles são usados para:

  • PIT recovery,
  • auditoria,
  • rollback histórico,
  • disaster recovery.

☕ COMO O Db2 ESCREVE NO LOG?

Muita gente acha que Db2 grava direto no disco.

Não.

Primeiro ele grava em:

🔥 LOG BUFFERS

na memória.

Depois:

  • COMMIT,
  • checkpoint,
  • buffer cheio,
  • sync I/O,

forçam gravação nos:

ACTIVE LOG DATASETS

🔥 WRITE AHEAD LOGGING (WAL)

Aqui está o segredo do recovery moderno.

O Db2 segue:

🔥 WAL — Write Ahead Logging

Regra:

“O log precisa ser gravado ANTES da página do banco.”

Isso garante:

  • rollback,
  • redo,
  • recuperação consistente.

Sem isso:
💀 corrupção.


☕ O QUE ACONTECE NUM COMMIT?

Quando o programa COBOL faz:

EXEC SQL COMMIT END-EXEC

o Db2:

  1. sincroniza logs,
  2. confirma UOW,
  3. libera locks,
  4. torna alterações permanentes.

O COMMIT é basicamente:

🔥 “Agora isso virou verdade oficial.”


☕ E NUM ABEND?

Aqui entra o terror psicológico do DBA.

Se ocorre:

  • S0C7,
  • S878,
  • timeout,
  • deadlock,
  • cancel,
  • crash,
  • queda de LPAR,

o Db2 usa os logs para:

🔥 ROLLBACK

Ele desfaz tudo desde o último COMMIT.


🔥 TIPOS DE ERRO MAIS COMUNS


⚠️ SQLCODE -911 / -913

Deadlock ou timeout

Dois programas querem recursos incompatíveis.

Exemplo clássico:

  • batch segurando tabela,
  • online tentando atualizar.

DBA/Sysprog:

  • analisar locking,
  • IFCID,
  • traces,
  • IRLM,
  • timeout values.

Programador COBOL:

  • reduzir tempo entre commits,
  • melhorar SQL,
  • evitar scan gigante.

⚠️ SQLCODE -904

Resource unavailable

Tablespace parado.
Utility rodando.
Objeto indisponível.

DBA:

  • verificar STOP status,
  • utilities,
  • claim/drain,
  • locks.

Sysprog:

  • investigar subsystem,
  • storage,
  • I/O,
  • coupling facility.

⚠️ SQLCODE -803

Duplicate key

Programador tentou inserir chave já existente.

Programador:

  • validar lógica,
  • tratar concorrência,
  • revisar sequence/identity.

DBA:

  • verificar índice,
  • constraints,
  • integridade.

⚠️ SQLCODE -805

Package não encontrado

Clássico inferno de deploy.

DBA:

  • verificar BIND,
  • PLAN/PACKAGE,
  • consistency token.

Sysprog:

  • SDSNLOAD,
  • STEPLIB,
  • DBRM libraries.

Programador:

  • garantir promote correto.

⚠️ 00C90084

Log full

Aqui o DBA começa a envelhecer rapidamente.

O active log lotou.

Possíveis causas:

  • UOW gigante,
  • commit inexistente,
  • archive parado.

DBA:

  • verificar ARCHIVE process,
  • aumentar logs,
  • cancelar job problemático.

Programador:

  • COMMIT frequente,
  • evitar transação monstruosa.

☕ COMO FUNCIONA O RECOVERY?

Aqui mora a mágica do Db2.


🔥 FORWARD RECOVERY

Db2:

  1. restaura image copy,
  2. reaplica logs.

Resultado:
✅ banco volta até ponto desejado.


🔥 BACKOUT / ROLLBACK

Db2 usa:

  • before images,
  • undo records.

E desfaz alterações.


🔥 RESTART RECOVERY

Após crash do subsystem:

Db2:

  • lê logs,
  • identifica UOW incompletas,
  • faz undo/redo automático.

Muitas vezes o usuário nem percebe.


☕ O PAPEL DO DBA

O DBA é o “cirurgião do banco”.

Ele:

  • monitora logs,
  • executa RECOVER,
  • controla utilities,
  • administra image copies,
  • resolve locking,
  • acompanha catalog,
  • analisa performance.

Ferramentas clássicas:

  • DSN1LOGP,
  • RECOVER,
  • COPY,
  • REORG,
  • DISPLAY DATABASE,
  • DISPLAY LOG.

☕ O PAPEL DO SYSPROG

O Sysprog atua na infraestrutura pesada.

Ele cuida:

  • do subsystem Db2,
  • IRLM,
  • z/OS,
  • JES,
  • storage,
  • coupling facility,
  • datasets de log,
  • BSDS,
  • bootstrap datasets.

Se o DBA é cirurgião…
o Sysprog é engenheiro nuclear.


☕ O QUE O PROGRAMADOR COBOL PRECISA ENTENDER?

Muito mais do que imaginam.

Porque SQL ruim gera:

  • lock,
  • timeout,
  • log storm,
  • escalation,
  • crash recovery lento.

🔥 Um bom programador Db2:

✅ faz commit racional
✅ evita cursor infinito
✅ reduz scans
✅ trata SQLCODE corretamente
✅ entende UOW
✅ sabe impacto do rollback
✅ evita transações gigantes


☕ O MAIOR ERRO DOS INICIANTES

Achar que:

COMMIT é só “salvar”.

Não.

COMMIT é:

  • sincronização,
  • liberação de lock,
  • persistência,
  • checkpoint lógico,
  • controle de recovery.

É o coração do Db2 transacional.


🔥 CONCLUSÃO

O log do Db2 é praticamente:

🔥 a memória do banco.

Sem ele:

  • não existe rollback,
  • recovery,
  • integridade,
  • restart,
  • consistência.

Quando você entende:

  • active log,
  • archive log,
  • WAL,
  • UOW,
  • rollback,
  • recovery,

você deixa de ser apenas “quem escreve SELECT”.

E começa a pensar como:

  • DBA,
  • sysprog,
  • arquiteto transacional.

E no universo mainframe…

isso muda tudo. ☕🔥

sexta-feira, 28 de novembro de 2025

💣🔥 TPS NÃO É THROUGHPUT — É O SEU “COMMIT FINANCEIRO” PASSANDO NO CICS 🔥💣

 

Bellacosa Mainframe CICS e throughput

💣🔥 TPS NÃO É THROUGHPUT — É O SEU “COMMIT FINANCEIRO” PASSANDO NO CICS 🔥💣

Se você entrou numa discussão de arquitetura falando de fila, banco NoSQL e multi-região antes de entender o que é dinheiro sendo movimentado, já começou igual job com JCL errado: vai rodar… mas vai dar abend.


⚙️ TPS vs Throughput — visão Bellacosa Mainframe

No mundo raiz (sim, aquele do CICS + DB2 + commit de verdade):

  • TPS (Transactions Per Second)
    👉 É o COMMIT EXECUTADO
    👉 É o dinheiro que mudou de dono
    👉 É o ponto sem volta
  • Throughput
    👉 É o volume de processamento
    👉 Inclui request, fila, validação, retry
    👉 Muito barulho… nem sempre dinheiro

💥 Tradução brutal:

Throughput é fila cheia.
TPS é saldo alterado com sucesso.

Se você tem:

  • 20k req/s entrando
  • 3k virando transação

👉 Você NÃO tem um sistema de 20k.
👉 Você tem um sistema de 3k TPS financeiro.


🌍 Multi-região — quando o sistema vira “sysplex global sem JES”

Quando você sai de uma região…

Você não escalou.
Você entrou em guerra.

Agora você tem:

  • 🌐 Latência: 100–200ms (no mínimo)
  • 🔄 Consistência distribuída
  • ⚠️ Conflito de escrita
  • 🔁 Failover real (não o de slide de PowerPoint)

💣 E aqui vem o ponto que derruba sistema:

TPS deixa de ser capacidade e vira problema de coordenação global.


💥 Onde TODO mundo quebra (sem exceção)

1. Consistência forte global

👉 “Vamos manter saldo sincronizado em todas regiões”

Resultado:

  • Lock distribuído
  • Round-trip global
  • TPS despenca mais rápido que job mal indexado

💣 Isso aqui mata performance.


2. Dependência síncrona entre regiões

👉 API Brasil → chama EUA → espera resposta

Resultado:

  • Cada request carrega latência global
  • Você virou refém da pior região

💣 É o equivalente moderno de:

“esperar fita montar pra continuar o batch”


3. Hotspot de dados

👉 Conta sendo acessada globalmente

Resultado:

  • Contenção
  • Locking
  • Throughput artificialmente alto… TPS real baixo

💣 Clássico erro de modelagem.


☠️ O ERRO RAIZ (o mais perigoso)

“Vamos usar Kafka”
“Vamos usar Cassandra”
“Vamos fazer active-active”

🚫 Errado.

Isso é igual dizer:

“Vamos usar DFSORT” antes de saber o layout do arquivo.


🧠 Modelo mental Bellacosa (nível arquiteto de guerra)

Antes de falar de tecnologia, responda:

1. Tipo de operação

  • 💰 Financeira crítica?
  • 🔁 Pode reprocessar?
  • ♻️ É idempotente?

2. Consistência

  • 🔒 Forte → saldo, ledger
  • 📊 Eventual → extrato, notificação

💣 Regra de ouro:

Quanto mais consistência, menor o TPS possível.


3. Latência aceitável

  • ⚡ 100ms?
  • 🕒 500ms?
  • 🔁 segundos com retry?

👉 Isso define TUDO.


4. Distribuição geográfica

  • Usuário local?
  • Cross-border?

👉 Se for global, esqueça sonho de consistência forte em tudo.


5. Perfil de carga

  • 📈 Constante?
  • 🚀 Pico violento?

👉 Sistema que aguenta pico não nasce por acidente.


🏦 Caso real (estilo “produção sem desculpa”)

Cenário:

  • 10k TPS global
  • Brasil + México
  • Transferência financeira

Estratégia inteligente

👉 Saldo = consistente localmente
👉 Cross-region = assíncrono

Fluxo mental:

  • Região BR resolve BR rápido
  • Região MX resolve MX rápido
  • Entre regiões → evento + reconciliação

⚖️ O trade-off que ninguém escapa

Você sempre escolhe entre:

  • 🔒 Consistência
  • ⚡ Latência
  • 🚀 Throughput

💣 Não existe arquitetura perfeita.
Existe arquitetura assumida com responsabilidade.


🔥 Conclusão estilo Bellacosa

Sistema financeiro não é sobre tecnologia.

É sobre decisão sob restrição real.

💣 Engenheiro júnior:

“Qual tecnologia usar?”

🔥 Engenheiro sênior:

“Qual risco eu posso aceitar?”


☕ Verdade final (nível mainframe raiz)

Se o seu TPS depende de coordenação global síncrona…

👉 você não construiu escala
👉 você construiu um gargalo distribuído

sábado, 31 de dezembro de 2022

COBOL, QSAM e Db2 sem Mistérios: a Jornada do Arquivo Sequencial até o INSERT na Tabela

 

Bellacosa Mainframe executando cobol com db2 e qsam

☕ Um Café no Bellacosa Mainframe

COBOL, QSAM e Db2 sem Mistérios: a Jornada do Arquivo Sequencial até o INSERT na Tabela

Imagine a cena: madrugada no datacenter, luzes azuis refletindo nos corredores, o IBM Z trabalhando silenciosamente e, diante da tela 3270, um programador COBOL padawan observa um pequeno JCL.

À primeira vista, são poucas linhas:

//EXECDB2 EXEC PGM=IKJEFT01,DYNAMNBR=20
//STEPLIB DD DSN=DSN910.SDSNLOAD,DISP=SHR
//LISTCOPAC DD DSN=INFEF00.COPIA.MUNDO,DISP=SHR
//SYSTSPRT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//SYSTSIN  DD *
  DSN SYSTEM(DB9G)
  RUN PROGRAM(COBDB501) PLAN(HERP0001) -
      LIB('ADCD.Z112.USERLOAD')
/*

Mas o verdadeiro mainframe nunca entrega todos os seus segredos de imediato.

Por trás dessas linhas existe uma cadeia completa de tecnologias:

JES2
  ↓
JCL
  ↓
IKJEFT01
  ↓
TSO Batch
  ↓
DSN Command Processor
  ↓
Db2 Attachment Facility
  ↓
PLAN
  ↓
PACKAGE
  ↓
Programa COBOL
  ↓
QSAM
  ↓
Arquivo sequencial
  ↓
INSERT no Db2
  ↓
COMMIT ou ROLLBACK

O JCL é pequeno, mas representa o último estágio de uma fábrica inteira de software. Antes de chegar a essa execução, alguém escreveu um programa COBOL, processou SQL pelo precompiler, compilou, linkeditou, gerou um load module, criou um DBRM, executou BIND PACKAGE, criou ou atualizou um PLAN e autorizou o usuário.

Vamos abrir cada porta desse templo tecnológico.


Bellacosa Mainframe executando um programa cobol db2 e qsam

1. Qual é a missão deste programa?

O próprio comentário do JCL entrega a missão:

//* PROGRAMA LE QSAM E INSERE TABELAS DB2

Em linguagem simples, o programa deverá:

  1. abrir um arquivo sequencial;

  2. ler cada registro;

  3. separar os campos;

  4. validar os dados;

  5. executar um INSERT em uma tabela Db2;

  6. tratar registros inválidos;

  7. realizar COMMIT;

  8. fechar o arquivo;

  9. retornar um código ao sistema operacional.

Um fluxo provável seria:

Abrir arquivo LISTCOPAC
        ↓
Ler primeiro registro
        ↓
Registro válido?
   ┌────┴────┐
   │         │
  Sim       Não
   │         │
INSERT      Registrar erro
   │         │
   └────┬────┘
        ↓
Atingiu intervalo de COMMIT?
        ↓
Executar COMMIT
        ↓
Ler próximo registro
        ↓
Fim do arquivo?
   ┌────┴────┐
   │         │
  Não       Sim
   │         │
Repetir     COMMIT final
             ↓
        Fechar arquivo
             ↓
           GOBACK

Esse tipo de programa é muito comum em sistemas corporativos.

Ele pode carregar:

  • clientes;

  • contas;

  • pagamentos;

  • movimentações;

  • produtos;

  • contratos;

  • dados de interfaces;

  • informações recebidas de outros sistemas;

  • arquivos produzidos por plataformas distribuídas.

É uma ponte entre o mundo dos arquivos batch e o mundo relacional do Db2.


2. O papel do JES

Antes que qualquer programa seja executado, o job precisa ser entregue ao JES.

JES significa Job Entry Subsystem.

Em muitos ambientes z/OS utiliza-se o JES2. Ele recebe o JCL, analisa as instruções, prepara os recursos, controla a execução e organiza as saídas no spool.

Quando o programador digita:

SUB

no ISPF Edit, não está executando o COBOL diretamente.

Na realidade, está entregando um pedido ao JES:

“JES, aceite este conjunto de instruções, valide o JCL, encontre os recursos e execute os steps na ordem indicada.”

O JES então:

  1. atribui um JOBID;

  2. lê o JCL;

  3. faz a conversão;

  4. verifica procedimentos;

  5. coloca o job na fila;

  6. seleciona uma initiator;

  7. executa os steps;

  8. recolhe as mensagens;

  9. grava os resultados no spool.

O nome mostrado na tela:

CATPGM1

é o nome do job.

O identificador:

JOB00056

é o JOBID atribuído pelo JES.

Esses dois nomes parecem semelhantes, mas representam coisas diferentes:

CATPGM1  = nome lógico fornecido no cartão JOB
JOB00056 = número atribuído pelo JES

3. A biblioteca JOBLIB

Na imagem existe:

//JOBLIB DD DSN=IBMUSER.CBL.LOADLIB,DISP=SHR

A JOBLIB define uma biblioteca de módulos executáveis para o job inteiro.

É como dizer:

“Ao procurar programas deste job, inclua esta biblioteca na busca.”

A biblioteca:

IBMUSER.CBL.LOADLIB

deve ser uma PDS ou PDSE contendo load modules ou program objects.

Um programa COBOL não é executado diretamente a partir do fonte:

IBMUSER.CBL.SOURCE(COBDB501)

O fonte precisa atravessar um processo:

Fonte COBOL
     ↓
Precompile Db2
     ↓
Compilação COBOL
     ↓
Object module
     ↓
Binder ou Link-edit
     ↓
Load module

O resultado final pode estar armazenado como:

IBMUSER.CBL.LOADLIB(COBDB501)

Um detalhe importante

No step da imagem também existe uma STEPLIB:

//STEPLIB DD DSN=DSN910.SDSNLOAD,DISP=SHR

Quando um step possui STEPLIB, ela normalmente substitui a JOBLIB para a busca de módulos naquele step.

Portanto, a existência de JOBLIB não significa que ela será usada pelo step EXECDB2.

Essa é uma daquelas curiosidades que derrubam muitos padawans.

O programador pensa:

“Meu programa está na JOBLIB, portanto será encontrado.”

Mas o sistema responde:

“Existe uma STEPLIB neste step. Minha busca seguirá outro caminho.”

No caso do JCL apresentado, o programa da aplicação é localizado por meio da cláusula:

LIB('ADCD.Z112.USERLOAD')

Isso evita que ele dependa da JOBLIB.


4. O step EXECDB2

//EXECDB2 EXEC PGM=IKJEFT01,DYNAMNBR=20

Essa linha cria um step chamado:

EXECDB2

O nome do step é escolhido pelo desenvolvedor.

Ele poderia ser:

//STEP01
//RUNCOB
//DB2RUN
//CARREGA

Um bom nome melhora a análise do spool.

Ao observar:

EXECDB2

já sabemos que aquele step provavelmente executará alguma coisa em um ambiente Db2.

A instrução:

EXEC PGM=IKJEFT01

determina o programa que o z/OS carregará inicialmente.

E aqui surge uma pergunta importante:

Por que o JCL não executa diretamente COBDB501?

Porque COBDB501 contém SQL estático e precisa executar conectado ao subsistema Db2. O IKJEFT01 cria o ambiente TSO batch, dentro do qual o command processor DSN estabelece essa conexão.

Assim, a sequência real é:

IKJEFT01
   ↓
Comando DSN
   ↓
DSN SYSTEM(DB9G)
   ↓
RUN PROGRAM(COBDB501)

5. O que é o IKJEFT01?

O IKJEFT01 é um programa do z/OS utilizado para executar comandos TSO em batch.

O TSO é normalmente associado ao trabalho interativo:

READY

O usuário digita comandos e recebe respostas.

Com IKJEFT01, não existe uma pessoa digitando os comandos. Eles são fornecidos por um dataset ou por dados instream no DD SYSTSIN.

Uma analogia Bellacosa:

  • TSO interativo é o Jedi no terminal;

  • IKJEFT01 é o droide que repete os comandos durante a madrugada;

  • SYSTSIN é o pergaminho com as ordens;

  • SYSTSPRT é o diário da missão.

O IKJEFT01 pode executar:

  • comandos TSO;

  • CLISTs;

  • execuções REXX;

  • comandos do Db2;

  • utilitários que dependem do ambiente TSO.


6. O parâmetro DYNAMNBR=20

DYNAMNBR=20

Esse parâmetro está relacionado ao número de alocações dinâmicas que o ambiente TSO pode utilizar.

Durante a execução, o IKJEFT01, o command processor DSN ou programas chamados podem precisar alocar datasets dinamicamente.

Exemplos:

  • bibliotecas;

  • arquivos temporários;

  • arquivos de controle;

  • mensagens;

  • datasets de trabalho.

O valor:

20

costuma ser suficiente para execuções simples.

Em ambientes maiores aparecem valores como:

DYNAMNBR=50

ou:

DYNAMNBR=100

Não significa que o sistema abrirá imediatamente 20 datasets. É uma capacidade reservada para o ambiente.

Um valor insuficiente pode provocar falhas de alocação em execuções mais complexas.


7. A STEPLIB do Db2

//STEPLIB DD DSN=DSN910.SDSNLOAD,DISP=SHR

A STEPLIB informa as bibliotecas usadas na procura dos programas daquele step.

A biblioteca:

DSN910.SDSNLOAD

contém módulos relacionados ao Db2.

Entre eles podem existir componentes necessários para:

  • iniciar o command processor DSN;

  • usar o TSO Attachment Facility;

  • conectar-se ao subsistema;

  • carregar rotinas internas;

  • interagir com os serviços Db2.

O nome DSN910 pode indicar uma instalação antiga, uma versão ou apenas uma convenção local.

Não devemos presumir que o nome da biblioteca representa exatamente a versão atual do Db2. Muitas instalações mantêm nomes históricos para evitar alterar centenas de JCLs.

Contudo, é essencial que essa biblioteca seja compatível com o subsistema usado.

O subsistema do exemplo é:

DB9G

Se a SDSNLOAD não for a correta, podem surgir:

  • mensagens de conexão;

  • módulo não encontrado;

  • falhas no attachment;

  • abends;

  • incompatibilidade de nível.


8. DISP=SHR

Tanto a JOBLIB quanto a STEPLIB e o arquivo de entrada utilizam:

DISP=SHR

O parâmetro DISP descreve o estado e o tratamento do dataset.

SHR significa que o dataset já existe e pode ser compartilhado.

Exemplo:

//STEPLIB DD DSN=DSN910.SDSNLOAD,DISP=SHR

Essa biblioteca poderá ser usada simultaneamente por vários jobs.

Isso é normal para load libraries, pois dezenas ou centenas de aplicações podem carregar módulos da mesma biblioteca.

No arquivo de entrada:

//LISTCOPAC DD DSN=INFEF00.COPIA.MUNDO,DISP=SHR

o SHR indica leitura compartilhada.

Se o programa estivesse atualizando diretamente um dataset, talvez fosse necessário:

DISP=OLD

Mas para leitura QSAM, SHR é a escolha mais comum.


9. O DD LISTCOPAC

//LISTCOPAC DD DSN=INFEF00.COPIA.MUNDO,DISP=SHR

Essa linha liga um nome lógico a um dataset físico.

O nome lógico é:

LISTCOPAC

O dataset físico é:

INFEF00.COPIA.MUNDO

No programa COBOL provavelmente existe:

SELECT ARQUIVO-COPAC
    ASSIGN TO LISTCOPAC
    ORGANIZATION IS SEQUENTIAL
    ACCESS MODE IS SEQUENTIAL
    FILE STATUS IS WS-FILE-STATUS.

O COBOL conhece o arquivo pelo nome lógico. O JCL informa qual dataset real será usado.

Essa separação é poderosa.

O mesmo programa pode processar arquivos diferentes sem precisar ser recompilado.

Hoje:

//LISTCOPAC DD DSN=INFEF00.COPIA.MUNDO,DISP=SHR

Amanhã:

//LISTCOPAC DD DSN=INFEF00.COPIA.MUNDO.NOVO,DISP=SHR

O programa continua igual.

É o JCL que conecta a aplicação ao dado certo.


10. O que é QSAM?

QSAM significa Queued Sequential Access Method.

É um método de acesso para datasets sequenciais.

O programa COBOL executa comandos simples:

OPEN INPUT
READ
CLOSE

Mas o QSAM trabalha nos bastidores com:

  • buffers;

  • blocos;

  • movimentação de dados;

  • controle de fim de arquivo;

  • tratamento de registros;

  • acesso ao dispositivo;

  • otimização de entrada e saída.

Imagine um arquivo com registros de 100 bytes:

LRECL=100

O sistema não precisa necessariamente ler um registro físico por operação de disco.

Ele pode ler um bloco contendo vários registros:

BLKSIZE=27900

Nesse caso, um bloco pode conter 279 registros de 100 bytes.

O programa continua pedindo um registro por vez, mas o QSAM já trouxe vários registros para a memória.

Essa é a magia silenciosa do buffering.


11. Exemplo de definição COBOL

Um arquivo poderia ter esta estrutura:

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.

    SELECT ARQ-COPAC
        ASSIGN TO LISTCOPAC
        ORGANIZATION IS SEQUENTIAL
        ACCESS MODE IS SEQUENTIAL
        FILE STATUS IS WS-FS-COPAC.

DATA DIVISION.
FILE SECTION.

FD  ARQ-COPAC
    RECORDING MODE IS F.

01  REG-COPAC.
    05 CP-CODIGO           PIC 9(05).
    05 CP-NOME             PIC X(40).
    05 CP-PAIS             PIC X(30).
    05 CP-POPULACAO        PIC 9(11).
    05 FILLER              PIC X(14).

O tamanho total seria:

5 + 40 + 30 + 11 + 14 = 100 bytes

Logo, o dataset deveria ter:

RECFM=FB
LRECL=100

Se o arquivo tiver LRECL=80, a definição estará incompatível.

O resultado pode ser:

  • erro de abertura;

  • registros truncados;

  • campos deslocados;

  • dados inválidos;

  • abend;

  • inserções incorretas no banco.


12. File Status: o sensor do arquivo

Todo programa COBOL profissional deveria usar FILE STATUS.

Exemplo:

01  WS-FS-COPAC         PIC XX.

Após o OPEN:

OPEN INPUT ARQ-COPAC

IF WS-FS-COPAC NOT = '00'
    DISPLAY 'ERRO NO OPEN DO ARQUIVO: ' WS-FS-COPAC
    MOVE 12 TO RETURN-CODE
    GOBACK
END-IF

Alguns estados comuns:

00 = operação concluída
10 = fim de arquivo
35 = arquivo não encontrado
39 = conflito de atributos
41 = arquivo já aberto
42 = arquivo não aberto
46 = tentativa inválida de READ

O status 39 merece atenção especial.

Ele pode ocorrer quando a definição física do arquivo não combina com o que o programa espera.

É o mainframe dizendo:

“Padawan, o arquivo existe, mas sua descrição não corresponde à realidade.”


13. O DD SYSTSPRT

//SYSTSPRT DD SYSOUT=*

O SYSTSPRT recebe mensagens do TSO e do command processor DSN.

É uma das saídas mais importantes para análise.

Ali podem aparecer:

  • início do DSN;

  • conexão com o subsistema;

  • processamento do comando RUN;

  • mensagens sobre PLAN;

  • falha na localização do programa;

  • retorno do ambiente Db2;

  • encerramento do command processor.

Quando o job falhar antes de entrar no programa COBOL, o SYSTSPRT deve ser uma das primeiras saídas examinadas.


14. O significado de SYSOUT=*

DD SYSOUT=*

Isso não significa “um arquivo chamado SYSOUT”.

SYSOUT=* envia a saída ao spool, usando normalmente a classe de saída definida pelo job.

Exemplo:

//SYSTSPRT DD SYSOUT=*

As mensagens poderão ser vistas no SDSF.

O asterisco significa, em termos práticos:

“Use a classe de saída padrão associada ao job.”

Também seria possível especificar uma classe:

//SYSTSPRT DD SYSOUT=X

A classe depende das regras da instalação.


15. O problema dos DDs duplicados

Na imagem aparecem duas linhas:

//SYSOUT DD SYSOUT=*
//SYSOUT DD SYSOUT=*

Esse é um provável erro.

Dentro do mesmo step, dois DD statements não devem possuir o mesmo DDNAME dessa maneira.

Se o programa precisa de duas saídas, use nomes diferentes:

//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*

Ou:

//RELATORI DD SYSOUT=*
//ERROS    DD SYSOUT=*

Os nomes devem corresponder ao que o programa espera.

Exemplo no COBOL:

SELECT ARQ-RELATORIO
    ASSIGN TO RELATORI.

SELECT ARQ-ERROS
    ASSIGN TO ERROS.

O JCL seria:

//RELATORI DD SYSOUT=*
//ERROS    DD SYSOUT=*

E se a intenção era concatenar?

A concatenação correta seria:

//ENTRADA  DD DSN=ARQUIVO.PARTE1,DISP=SHR
//         DD DSN=ARQUIVO.PARTE2,DISP=SHR

Observe que apenas a primeira linha possui DDNAME.

Portanto:

//SYSOUT DD SYSOUT=*
//SYSOUT DD SYSOUT=*

não é a maneira adequada de concatenar.


16. O DD SYSTSIN

//SYSTSIN DD *

O SYSTSIN fornece comandos ao ambiente TSO batch.

Tudo entre:

//SYSTSIN DD *

e:

/*

será entregue ao IKJEFT01.

No exemplo:

DSN SYSTEM(DB9G)
RUN PROGRAM(COBDB501) PLAN(HERP0001) -
    LIB('ADCD.Z112.USERLOAD')

Essas linhas não são JCL.

São comandos processados dentro do ambiente TSO/Db2.

Essa diferença é fundamental.

JCL:

//SYSTSIN DD *

Comando TSO:

DSN SYSTEM(DB9G)

Subcomando Db2:

RUN PROGRAM(COBDB501)

17. O comando DSN SYSTEM(DB9G)

DSN SYSTEM(DB9G)

O comando DSN inicia o command processor do Db2.

O parâmetro:

SYSTEM(DB9G)

identifica o subsistema desejado.

O nome de quatro caracteres:

DB9G

é o subsystem ID.

Em outros ambientes poderíamos encontrar:

DB2D
DB2T
DB2H
DB2P
D91A
DSN1

A convenção varia.

Por exemplo:

DB2D = desenvolvimento
DB2T = teste
DB2H = homologação
DB2P = produção

Mas essa nomenclatura não é uma regra do Db2. É apenas uma convenção possível.

Quando o comando é executado, o sistema tenta:

  1. localizar o subsistema;

  2. estabelecer o attachment;

  3. criar uma thread;

  4. validar o ambiente;

  5. preparar a execução do programa.

Se o subsistema estiver parado, o programa nem chegará a ser carregado.


18. O comando RUN PROGRAM

RUN PROGRAM(COBDB501)

O DSN recebe a ordem para executar o programa:

COBDB501

Esse nome deve corresponder ao load module ou program object gerado no link-edit.

O DSN não executa o fonte COBOL.

Ele procura algo como:

ADCD.Z112.USERLOAD(COBDB501)

O membro deve ser um executável válido.

Se o membro não existir, pode ocorrer uma mensagem de programa não encontrado ou até um abend S806, dependendo do ponto da falha.


19. A cláusula PLAN(HERP0001)

PLAN(HERP0001)

O PLAN representa o contexto de execução Db2 da aplicação.

Historicamente, o PLAN continha diretamente os DBRMs.

Nos ambientes modernos, é comum o PLAN apontar para PACKAGES:

PLAN
  ↓
PKLIST
  ↓
COLLECTION
  ↓
PACKAGE
  ↓
Seções SQL

O PLAN:

HERP0001

deve existir no subsistema DB9G.

Também precisa estar autorizado para o usuário que executa o job.

Caso contrário, podem surgir erros relacionados a:

  • autorização;

  • PLAN inexistente;

  • PACKAGE não localizado;

  • collection incorreta;

  • inconsistência entre programa e PACKAGE.


20. DBRM, PACKAGE e PLAN

Quando um programa COBOL contém SQL:

EXEC SQL
    INSERT INTO TB_COPAC
           (CODIGO, NOME, PAIS)
    VALUES (:CP-CODIGO, :CP-NOME, :CP-PAIS)
END-EXEC

o compilador COBOL não entende sozinho esse SQL.

Antes da compilação, ocorre o precompile Db2.

O precompiler produz dois resultados:

1. Fonte COBOL modificado
2. DBRM

O fonte modificado contém chamadas à interface Db2.

O DBRM contém as instruções SQL extraídas.

Fluxo completo:

COBOL + SQL
    ↓
PRECOMPILE
    ├── COBOL modificado
    └── DBRM
          ↓
      BIND PACKAGE
          ↓
       PACKAGE

Enquanto isso:

COBOL modificado
    ↓
COMPILER
    ↓
OBJECT MODULE
    ↓
LINK-EDIT
    ↓
LOAD MODULE

Na execução, o load module e o PACKAGE precisam pertencer à mesma geração lógica.


21. O clássico SQLCODE -818

O -818 ocorre quando o programa executável e o DBRM ou PACKAGE não possuem o mesmo consistency token.

Em linguagem Bellacosa:

O sabre de luz e o cristal kyber vieram de treinamentos diferentes.

Isso acontece quando:

  1. o programa é precompilado;

  2. é gerado um novo DBRM;

  3. o COBOL é compilado;

  4. o load module é atualizado;

  5. o PACKAGE antigo continua no Db2.

Ou o contrário:

  1. um novo PACKAGE é criado;

  2. o load module antigo continua na loadlib.

Resultado:

SQLCODE -818

A correção normalmente exige refazer o ciclo com os mesmos artefatos:

PRECOMPILE
COMPILE
LINK-EDIT
BIND PACKAGE

22. O SQLCODE -805

O -805 também é extremamente comum.

Ele indica que o Db2 não encontrou o PACKAGE necessário.

Possíveis causas:

  • PACKAGE não bindado;

  • collection errada;

  • PLAN não contém a collection;

  • nome do programa diferente;

  • ambiente errado;

  • PACKAGE removido;

  • load module promovido sem o BIND correspondente.

A mensagem geralmente fornece informações sobre:

  • localização;

  • collection;

  • package;

  • consistency token.

Esses dados devem ser analisados cuidadosamente.


23. A cláusula LIB

LIB('ADCD.Z112.USERLOAD')

A cláusula LIB informa a biblioteca onde o programa deve ser localizado.

Portanto:

RUN PROGRAM(COBDB501)
    PLAN(HERP0001)
    LIB('ADCD.Z112.USERLOAD')

significa:

Execute o programa COBDB501, utilizando o PLAN HERP0001, procurando o módulo na biblioteca ADCD.Z112.USERLOAD.

Essa instrução é importante porque a STEPLIB contém apenas a biblioteca Db2.

Sem a cláusula LIB, o programa da aplicação talvez não fosse encontrado.

Atenção à biblioteca antiga

A imagem também mostra:

//JOBLIB DD DSN=IBMUSER.CBL.LOADLIB,DISP=SHR

Temos então duas bibliotecas que podem conter o programa:

IBMUSER.CBL.LOADLIB
ADCD.Z112.USERLOAD

É importante confirmar onde está a versão correta.

Talvez exista:

IBMUSER.CBL.LOADLIB(COBDB501)

e também:

ADCD.Z112.USERLOAD(COBDB501)

Se a versão nova foi gravada na primeira biblioteca, mas o comando RUN aponta para a segunda, o job continuará executando o programa antigo.

Esse é um easter egg clássico do mainframe:

O código está correto, a compilação terminou com RC 0, mas o comportamento não mudou porque o job está carregando outra cópia do programa.

Para investigar, use ISPF 3.4 e compare:

  • data;

  • hora;

  • tamanho;

  • atributos;

  • usuário da última alteração.


24. O hífen de continuação

PLAN(HERP0001) -

O hífen informa que o comando continua na linha seguinte.

A continuação é:

LIB('ADCD.Z112.USERLOAD')

Sem o hífen, o DSN poderia tratar a primeira linha como um comando completo e a segunda como outro comando.

Uma versão bem formatada seria:

RUN PROGRAM(COBDB501) -
    PLAN(HERP0001)     -
    LIB('ADCD.Z112.USERLOAD')

O estilo depende do padrão da empresa, mas a legibilidade melhora bastante.


25. O comando END

O JCL da imagem não apresenta explicitamente:

END

É recomendável encerrar a sessão DSN:

//SYSTSIN DD *
  DSN SYSTEM(DB9G)
  RUN PROGRAM(COBDB501) PLAN(HERP0001) -
      LIB('ADCD.Z112.USERLOAD')
  END
/*

O fim do arquivo de comandos pode encerrar o command processor, mas o END deixa a intenção explícita.

É uma boa prática.


26. Exemplo completo de JCL corrigido

//CATPGM1 JOB (ACCT),'CARGA COBOL DB2',
//             CLASS=A,
//             MSGCLASS=X,
//             MSGLEVEL=(1,1),
//             NOTIFY=&SYSUID
//*
//*-------------------------------------------------------------------*
//* PROGRAMA COBOL LE ARQUIVO QSAM E INSERE DADOS NO DB2
//*-------------------------------------------------------------------*
//EXECDB2 EXEC PGM=IKJEFT01,DYNAMNBR=20
//*
//* MODULOS DO DB2
//*
//STEPLIB DD DSN=DSN910.SDSNLOAD,DISP=SHR
//*
//* ARQUIVO SEQUENCIAL DE ENTRADA
//*
//LISTCOPAC DD DSN=INFEF00.COPIA.MUNDO,DISP=SHR
//*
//* SAIDAS DO AMBIENTE E DO PROGRAMA
//*
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//CEEDUMP  DD SYSOUT=*
//*
//* COMANDOS TSO E DB2
//*
//SYSTSIN DD *
  DSN SYSTEM(DB9G)
  RUN PROGRAM(COBDB501) PLAN(HERP0001) -
      LIB('ADCD.Z112.USERLOAD')
  END
/*
//

27. Explicação do cartão JOB

//CATPGM1 JOB (ACCT),'CARGA COBOL DB2',

CATPGM1 é o nome do job.

(ACCT)

representa informações contábeis da instalação.

'CARGA COBOL DB2'

é uma descrição.


CLASS=A

CLASS=A

Define a classe de execução.

A classe pode determinar:

  • prioridade;

  • initiator;

  • limites;

  • ambiente;

  • políticas de scheduling.

O significado de A varia conforme a instalação.


MSGCLASS=X

MSGCLASS=X

Define a classe das mensagens de saída.

Ela influencia onde e como o spool será tratado.


MSGLEVEL=(1,1)

MSGLEVEL=(1,1)

Controla o nível de detalhes registrado no spool.

O primeiro valor controla a impressão das instruções JCL.

O segundo controla mensagens de alocação e execução.


NOTIFY=&SYSUID

NOTIFY=&SYSUID

Solicita que o usuário que submeteu o job seja notificado quando ele terminar.

&SYSUID é substituído pelo ID do usuário.


28. Exemplo de programa COBOL

       IDENTIFICATION DIVISION.
       PROGRAM-ID. COBDB501.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.

           SELECT ARQ-COPAC
               ASSIGN TO LISTCOPAC
               ORGANIZATION IS SEQUENTIAL
               ACCESS MODE IS SEQUENTIAL
               FILE STATUS IS WS-FS-COPAC.

       DATA DIVISION.
       FILE SECTION.

       FD  ARQ-COPAC
           RECORDING MODE IS F.

       01  REG-COPAC.
           05 CP-CODIGO           PIC 9(05).
           05 CP-NOME             PIC X(40).
           05 CP-PAIS             PIC X(30).
           05 CP-POPULACAO        PIC 9(11).
           05 FILLER              PIC X(14).

       WORKING-STORAGE SECTION.

       01  WS-FS-COPAC            PIC XX.
       01  WS-FIM-ARQUIVO         PIC X VALUE 'N'.
           88 FIM-ARQUIVO               VALUE 'S'.

       01  WS-CONTADORES.
           05 WS-LIDOS            PIC 9(09) COMP-3 VALUE ZERO.
           05 WS-INSERIDOS        PIC 9(09) COMP-3 VALUE ZERO.
           05 WS-REJEITADOS       PIC 9(09) COMP-3 VALUE ZERO.
           05 WS-COMMIT           PIC 9(05) COMP-3 VALUE ZERO.

       01  WS-SQLCODE-AUX         PIC -9(09).

           EXEC SQL
               INCLUDE SQLCA
           END-EXEC.

       PROCEDURE DIVISION.

       0000-PRINCIPAL.

           PERFORM 1000-INICIALIZAR

           PERFORM 2000-PROCESSAR
               UNTIL FIM-ARQUIVO

           PERFORM 9000-FINALIZAR

           GOBACK.

29. Inicialização do programa

       1000-INICIALIZAR.

           DISPLAY 'INICIO DO PROGRAMA COBDB501'

           OPEN INPUT ARQ-COPAC

           IF WS-FS-COPAC NOT = '00'
               DISPLAY 'ERRO NO OPEN LISTCOPAC: ' WS-FS-COPAC
               MOVE 12 TO RETURN-CODE
               GOBACK
           END-IF

           PERFORM 2100-LER-ARQUIVO.

A primeira leitura é realizada na inicialização.

Esse padrão evita que o programa execute o processamento com um registro não carregado.


30. Leitura e processamento

       2000-PROCESSAR.

           ADD 1 TO WS-LIDOS

           PERFORM 3000-VALIDAR-REGISTRO

           IF CP-CODIGO IS NUMERIC
               PERFORM 4000-INSERIR-DB2
           ELSE
               ADD 1 TO WS-REJEITADOS
               DISPLAY 'CODIGO INVALIDO: ' CP-CODIGO
           END-IF

           PERFORM 2100-LER-ARQUIVO.

A leitura:

       2100-LER-ARQUIVO.

           READ ARQ-COPAC
               AT END
                   SET FIM-ARQUIVO TO TRUE
               NOT AT END
                   CONTINUE
           END-READ

           IF WS-FS-COPAC NOT = '00'
              AND WS-FS-COPAC NOT = '10'
               DISPLAY 'ERRO DE LEITURA: ' WS-FS-COPAC
               PERFORM 8000-ROLLBACK
               MOVE 12 TO RETURN-CODE
               GOBACK
           END-IF.

O status 10 representa fim de arquivo e não deve ser tratado como erro.


31. O INSERT Db2

       4000-INSERIR-DB2.

           EXEC SQL
               INSERT INTO TB_COPAC
               (
                   CODIGO,
                   NOME,
                   PAIS,
                   POPULACAO
               )
               VALUES
               (
                   :CP-CODIGO,
                   :CP-NOME,
                   :CP-PAIS,
                   :CP-POPULACAO
               )
           END-EXEC

           EVALUATE SQLCODE
               WHEN ZERO
                   ADD 1 TO WS-INSERIDOS
                   ADD 1 TO WS-COMMIT

               WHEN -803
                   ADD 1 TO WS-REJEITADOS
                   DISPLAY 'CHAVE DUPLICADA: ' CP-CODIGO

               WHEN OTHER
                   MOVE SQLCODE TO WS-SQLCODE-AUX
                   DISPLAY 'ERRO SQL: ' WS-SQLCODE-AUX
                   DISPLAY 'REGISTRO: ' CP-CODIGO
                   PERFORM 8000-ROLLBACK
                   MOVE 12 TO RETURN-CODE
                   GOBACK
           END-EVALUATE

           IF WS-COMMIT >= 1000
               PERFORM 7000-COMMIT
           END-IF.

32. Por que não fazer apenas um COMMIT no final?

Imagine uma carga de dez milhões de registros.

Se o programa executar um único COMMIT, poderá manter durante horas:

  • locks;

  • espaço de log;

  • páginas modificadas;

  • recursos;

  • unidade de trabalho gigantesca.

Se ocorrer erro no registro 9.999.999, o rollback poderá desfazer tudo.

Uma estratégia mais segura é:

COMMIT a cada 1.000 registros

Ou:

COMMIT a cada 5.000 registros

O valor ideal depende do ambiente.

Não existe um número mágico.

É preciso considerar:

  • volume;

  • concorrência;

  • log;

  • índices;

  • tempo de recuperação;

  • SLA;

  • restart;

  • regras de negócio.

Rotina:

       7000-COMMIT.

           EXEC SQL
               COMMIT
           END-EXEC

           IF SQLCODE NOT = ZERO
               DISPLAY 'ERRO NO COMMIT: ' SQLCODE
               MOVE 12 TO RETURN-CODE
               GOBACK
           END-IF

           MOVE ZERO TO WS-COMMIT.

33. ROLLBACK

       8000-ROLLBACK.

           EXEC SQL
               ROLLBACK
           END-EXEC

           DISPLAY 'ROLLBACK EXECUTADO'.

O rollback desfaz alterações realizadas desde o último commit.

Mas atenção: ele não desfaz tudo desde o início do programa se já ocorreram commits intermediários.

Exemplo:

1.000 registros → COMMIT
1.000 registros → COMMIT
500 registros → erro → ROLLBACK

Nesse caso:

  • os primeiros 2.000 permanecem;

  • os últimos 500 são desfeitos.


34. Finalização

       9000-FINALIZAR.

           IF WS-COMMIT > ZERO
               PERFORM 7000-COMMIT
           END-IF

           CLOSE ARQ-COPAC

           DISPLAY '--------------------------------'
           DISPLAY 'REGISTROS LIDOS     : ' WS-LIDOS
           DISPLAY 'REGISTROS INSERIDOS : ' WS-INSERIDOS
           DISPLAY 'REGISTROS REJEITADOS: ' WS-REJEITADOS
           DISPLAY 'FIM DO PROGRAMA COBDB501'
           DISPLAY '--------------------------------'.

Esses totais serão enviados ao SYSOUT ou à saída padrão do Language Environment, dependendo da configuração.

Eles são fundamentais para auditoria.


35. Códigos de retorno

O programa pode usar:

MOVE 0 TO RETURN-CODE

para sucesso.

Outros códigos comuns:

RC 0  = sucesso
RC 4  = sucesso com aviso
RC 8  = erro de aplicação
RC 12 = erro grave
RC 16 = falha crítica

Esses valores são convenções. A empresa pode definir outros padrões.

Um scheduler pode usar o retorno:

RC <= 4  → continuar
RC >= 8  → interromper fluxo

36. Possíveis falhas

JCL ERROR

Causa provável:

//SYSOUT DD SYSOUT=*
//SYSOUT DD SYSOUT=*

Correção: usar DDNAMEs distintos.


S806

O programa não foi encontrado.

Verificar:

ADCD.Z112.USERLOAD(COBDB501)

S013

Pode estar relacionado à incompatibilidade de atributos do dataset.

Verificar:

  • RECFM;

  • LRECL;

  • BLKSIZE;

  • modo de abertura;

  • definição FD.


SQLCODE -803

Chave duplicada.

O programa tentou inserir um valor único já existente.


SQLCODE -805

PACKAGE não encontrado.

Verificar:

  • collection;

  • BIND PACKAGE;

  • PLAN;

  • consistency token.


SQLCODE -818

Load module e PACKAGE incompatíveis.

Refazer compilação e BIND de forma sincronizada.


SQLCODE -904

Recurso indisponível.

Pode existir:

  • tablespace parado;

  • utility pendente;

  • objeto em estado restritivo;

  • problema de storage.


SQLCODE -911

Deadlock ou timeout com rollback.

A aplicação precisa registrar:

  • chave;

  • SQLCODE;

  • unidade de trabalho;

  • momento do erro.


SQLCODE -922

Problema de autorização ou conexão.

Verificar permissões para:

  • PLAN;

  • PACKAGE;

  • tabela;

  • operação INSERT;

  • subsistema.


37. Como investigar no SDSF

Depois de submeter o job, abra:

SDSF

Depois:

ST

Localize o job e abra com S.

Analise na seguinte ordem:

JESJCL

Mostra o JCL interpretado.

Útil para detectar:

  • erro de sintaxe;

  • DD duplicado;

  • PROC expandida;

  • símbolos substituídos.

JESYSMSG

Mostra mensagens do sistema.

Procure por prefixos:

IEF
IEC
IGD
ICH

SYSTSPRT

Mostra mensagens do TSO e DSN.

SYSOUT

Mostra os DISPLAY do COBOL.

CEEDUMP

Mostra informações de falhas do Language Environment.

SYSUDUMP

Pode conter detalhes de abend e registradores.


38. Easter egg: o programa antigo que nunca morre

Um dos problemas mais misteriosos do mainframe ocorre assim:

  1. o programador altera o fonte;

  2. compila com RC 0;

  3. submete o job;

  4. o comportamento antigo continua;

  5. compila novamente;

  6. nada muda;

  7. começa a desconfiar do compilador, do Db2 e talvez da própria realidade.

A causa:

O load module foi gravado em uma biblioteca,
mas o RUN está usando outra.

Exemplo:

Novo:
IBMUSER.CBL.LOADLIB(COBDB501)

Executado:
ADCD.Z112.USERLOAD(COBDB501)

O mainframe não está errado.

Ele apenas obedeceu exatamente ao que foi pedido.

Essa é uma das grandes lições do IBM Z:

O sistema raramente faz o que imaginamos. Ele faz o que realmente declaramos.


39. O grande mapa da missão

INFEF00.COPIA.MUNDO
          │
          │ LISTCOPAC
          ▼
     Programa COBOL
       COBDB501
          │
          │ EXEC SQL INSERT
          ▼
      PLAN HERP0001
          │
          ▼
        PACKAGE
          │
          ▼
       Db2 DB9G
          │
          ▼
       TB_COPAC

Ao redor dessa execução, estão:

JES2
IKJEFT01
SDSNLOAD
TSO Attachment
Language Environment
QSAM
RACF
SDSF
Logs do Db2

Nada acontece isoladamente.


Conclusão: poucas linhas, muitas engrenagens

O JCL apresentado é um excelente exemplo da filosofia mainframe: comandos pequenos podem coordenar estruturas gigantescas.

Uma linha como:

RUN PROGRAM(COBDB501) PLAN(HERP0001)

carrega décadas de evolução tecnológica.

Ela conecta:

  • um executável COBOL;

  • um ambiente TSO batch;

  • um subsistema Db2;

  • um PLAN;

  • PACKAGES;

  • SQL estático;

  • um arquivo sequencial;

  • QSAM;

  • segurança;

  • logging;

  • controle transacional.

Para o programador COBOL padawan, a principal lição é não observar o JCL como uma simples receita de execução.

Cada DD representa um contrato.

LISTCOPAC → contrato com o arquivo
STEPLIB   → contrato com as bibliotecas
SYSTSIN   → contrato com o TSO
SYSTSPRT  → contrato com as mensagens
PLAN      → contrato com o Db2
LIB       → contrato com o executável
COMMIT    → contrato com a integridade

Quando esses contratos estão alinhados, milhões de registros podem ser processados com precisão.

Quando um deles está errado, o sistema pode responder com um JCL ERROR, um S806, um -805, um -818 ou um silencioso arquivo lido com layout incorreto.

O verdadeiro domínio do mainframe não vem apenas de decorar comandos.

Ele nasce quando entendemos a jornada completa:

Fonte
  → Precompile
  → Compile
  → Link-edit
  → DBRM
  → BIND PACKAGE
  → BIND PLAN
  → JCL
  → IKJEFT01
  → DSN
  → COBOL
  → QSAM
  → Db2
  → COMMIT
  → SDSF

E assim, diante da tela verde, com uma caneca de café ao lado, o padawan percebe que aquele pequeno JCL não é apenas um arquivo de comandos.

É a porta de entrada para uma das arquiteturas de processamento corporativo mais robustas já construídas.

segunda-feira, 9 de maio de 2022

GIT - O Que Todo Programador COBOL Padawan Precisa Saber Sobre Controle de Versão Profissional na Era da Inteligência Artificial, DevOps e IBM Mainframe

 

Bellacosa Mainframe muito alem do git commit

☕ Um Café no Bellacosa Mainframe

Git Muito Além do git commit

O Que Todo Programador COBOL Padawan Precisa Saber Sobre Controle de Versão Profissional na Era da Inteligência Artificial, DevOps e IBM Mainframe

"Existe uma enorme diferença entre saber usar comandos do Git e compreender como o Git realmente pensa. É exatamente essa diferença que separa um programador que apenas grava código de um engenheiro de software capaz de colaborar em projetos globais."


Introdução

Recentemente encontrei uma imagem bastante interessante intitulada "Top 20 Git Commands Every Developer Should Know". À primeira vista, ela parece apenas mais um resumo para consulta rápida.

Ela lista comandos como:

  • git init

  • git clone

  • git add

  • git commit

  • git push

  • git pull

e muitos outros.

Para um desenvolvedor iniciante, essa imagem parece representar praticamente todo o universo do Git.

Mas existe um detalhe importante.

Ela mostra o volante, o acelerador e o freio.

Ela não mostra o motor.

E quem trabalha com sistemas críticos — especialmente quem vem do universo IBM Mainframe — sabe que entender somente os comandos nunca foi suficiente.

No mundo do z/OS não basta decorar:

IEFBR14

É preciso entender:

  • JES2

  • Address Space

  • Dispatching

  • Storage

  • Dataset Catalog

  • VSAM

  • RACF

  • SMF

  • WLM

Da mesma forma, no Git não basta decorar comandos.

É preciso entender a arquitetura.

Hoje vamos tomar um café e mergulhar no funcionamento interno do Git.


Git não é apenas um programa

O Git é um Sistema Distribuído de Controle de Versão (Distributed Version Control System - DVCS).

Essa definição parece simples.

Mas ela muda completamente a forma como o desenvolvimento acontece.

Antes do Git existiam ferramentas como:

  • CVS

  • SourceSafe

  • SVN

Todas eram centralizadas.

Imagine um servidor.

Servidor

     Projeto

Todos os desenvolvedores dependiam dele.

Se o servidor parasse...

Ninguém trabalhava.

Se a rede caísse...

Ninguém fazia commit.


O Git mudou completamente essa arquitetura

Quando você executa:

git clone

Você não baixa apenas os arquivos.

Você baixa:

  • todos os commits

  • todas as branches

  • todas as tags

  • todo o histórico

Na prática, você cria um espelho completo do repositório.

É como se cada desenvolvedor carregasse um mini GitHub dentro do notebook.


Fazendo uma analogia com o Mainframe

Imagine um enorme PDS onde vivem todos os programas COBOL.

Agora imagine que cada desenvolvedor possui uma cópia completa daquele PDS, incluindo todas as versões desde a criação do sistema.

É exatamente isso que o Git faz.

Só que muito melhor.


A pasta mais importante do projeto

Quando executamos:

git init

Algo aparentemente simples acontece.

É criada uma pasta escondida.

.git

Muitos iniciantes ignoram essa pasta.

Grande erro.

É nela que mora todo o Git.

Se ela desaparecer...

O histórico desaparece.

Os commits desaparecem.

As branches desaparecem.

As tags desaparecem.

O projeto volta a ser apenas uma pasta comum.


O que existe dentro da pasta .git?

Normalmente encontramos algo parecido com isto:

.git

objects

refs

HEAD

config

hooks

logs

index

packed-refs

Cada item possui uma função específica.


objects

É o verdadeiro banco de dados do Git.

Tudo fica aqui.

Arquivos.

Commits.

Branches.

Trees.

Tags.

Tudo.


refs

São os ponteiros.

Eles dizem onde cada branch está.


HEAD

É o famoso ponteiro atual.

Sempre indica onde você está trabalhando.


config

Contém toda configuração local.

Usuário.

Email.

Remotos.

Aliases.


hooks

Automação.

Podemos executar scripts antes de:

  • commit

  • push

  • merge

Muito usado em DevOps.


O Git não salva diferenças

Essa talvez seja a maior surpresa para quem começa.

Muitos acreditam que o Git grava apenas as linhas modificadas.

Não.

Ele trabalha principalmente com snapshots.

Imagine um diretório.

Projeto

Programa1.cbl

Programa2.cbl

JCL1.jcl

README.md

Quando fazemos:

git commit

O Git registra um retrato completo daquele momento.

Como uma fotografia.

Não apenas um patch.

Isso torna a recuperação extremamente eficiente.


Os quatro tipos de objetos do Git

O banco interno do Git possui apenas quatro tipos fundamentais.

Blob

Representa o conteúdo de um arquivo.

Não conhece nomes.

Não conhece diretórios.

Conhece apenas bytes.


Tree

Organiza os blobs.

Funciona como um diretório.


Commit

Liga uma árvore ao histórico.

Contém:

  • autor

  • data

  • mensagem

  • commit anterior


Tag

Marca um commit especial.

Normalmente versões:

v1.0

v2.0

Release-2026

SHA: a identidade única de tudo

Cada objeto recebe um hash.

Exemplo:

c83f92b15c4...

Esse hash é calculado sobre o conteúdo.

Se um único byte mudar...

Todo o hash muda.

Essa característica garante integridade.


Os três estados dos arquivos

Esse é provavelmente o conceito mais importante do Git.

Todo arquivo percorre três etapas.

Working Directory

↓

Staging Area

↓

Repository

Working Directory

É onde editamos.

Abrimos o COBOL.

Mudamos um SELECT.

Alteramos um PERFORM.

Ainda não existe histórico.


Staging Area

É uma área intermediária.

O comando:

git add

Não grava nada.

Ele apenas prepara.

É como colocar documentos sobre a mesa antes de arquivá-los.


Repository

Somente quando executamos:

git commit

O histórico realmente nasce.


Git Status

Se existisse apenas um comando obrigatório seria:

git status

Ele responde perguntas como:

  • O que mudou?

  • O que será enviado?

  • O que ainda não entrou no commit?

Executar esse comando diversas vezes ao longo do dia é uma excelente prática.


Git Add

Existe uma diferença enorme entre:

git add arquivo.cbl

e

git add .

O primeiro adiciona apenas um arquivo.

O segundo adiciona praticamente tudo.

Isso inclui arquivos temporários.

Logs.

Arquivos de configuração.

Até senhas esquecidas.

Daí nasce a importância do:

.gitignore

Git Ignore

Imagine esquecer dentro do projeto:

senha.txt

backup.zip

log.txt

database.db

Sem o .gitignore, tudo isso pode ir para o repositório.

Alguns vazamentos famosos de credenciais ocorreram exatamente por causa disso.


Commits são sua documentação

Existe um velho hábito ruim.

Update

Outro.

Correções

Outro.

Mudanças

Meses depois...

Ninguém sabe o que foi alterado.

Uma boa mensagem explica a intenção.

Por exemplo:

Valida CPF antes da gravação no DB2

ou

Corrige cálculo do IOF para operações acima de R$ 50.000

Muito mais útil.


Branches: linhas paralelas de desenvolvimento

Imagine um banco.

Enquanto uma equipe trabalha no PIX...

Outra trabalha no Open Finance.

Outra corrige produção.

Tudo ao mesmo tempo.

Isso só é possível porque existem branches.

main

├── feature-pix

├── feature-openfinance

└── hotfix

Cada equipe trabalha isoladamente.


Merge

Quando uma funcionalidade termina:

feature-pix

ela precisa voltar para:

main

É aqui que entra o:

git merge

Ele une dois históricos.


Conflitos

Imagine dois desenvolvedores alterando a mesma linha.

Um escreve:

MOVE ZERO TO WS-TOTAL.

Outro escreve:

MOVE WS-VALOR TO WS-TOTAL.

Quem está certo?

O Git não decide.

Ele apresenta:

<<<<<<<
=======
>>>>>>>

E cabe ao desenvolvedor resolver.


Fetch versus Pull

Muitos iniciantes acreditam que são iguais.

Não são.

git fetch

Baixa novidades.

Mas não altera seu trabalho.

Já:

git pull

Baixa e integra imediatamente.

É praticamente:

fetch

+

merge

Em projetos críticos, muitos profissionais preferem primeiro:

git fetch

Analisar.

Depois integrar.


Push

Sem ele ninguém verá seu trabalho.

git push

Envia seus commits ao servidor.

É a promoção do desenvolvimento local para o repositório compartilhado.


Git Diff

Antes de qualquer commit execute:

git diff

Você verá exatamente:

-

+

Tudo que será enviado.

Isso evita inúmeros erros.


Git Stash

Imagine este cenário.

Você está desenvolvendo uma API.

Surge uma emergência em produção.

Você ainda não pode fazer commit.

O que fazer?

git stash

Ele guarda temporariamente tudo.

Depois:

git stash pop

Seu trabalho retorna exatamente como estava.


Git Reset

Esse comando merece respeito.

Especialmente:

git reset --hard

Ele pode apagar alterações locais sem possibilidade simples de recuperação.

Não é um comando para testar.

É um comando para compreender profundamente antes de usar.


O verdadeiro poder das branches

No Git, uma branch é extremamente leve.

Ela não copia o projeto.

Ela cria apenas um ponteiro.

Por isso podemos criar dezenas ou centenas delas.


O Git e o DevOps

Hoje praticamente toda pipeline utiliza Git.

Por exemplo:

Commit

↓

GitHub

↓

GitHub Actions

↓

Build

↓

Testes

↓

Deploy

↓

Produção

Sem Git praticamente não existe DevOps moderno.


GitHub não é Git

Outro erro muito comum.

Git é uma tecnologia.

GitHub é um serviço.

Também existem:

  • GitLab

  • Bitbucket

  • Azure DevOps

  • Gitea

  • Forgejo

Todos utilizam Git.


Git e Inteligência Artificial

Ferramentas como:

  • GitHub Copilot

  • ChatGPT

  • Claude

  • Gemini

podem escrever código.

Mas todas dependem de algo extremamente importante.

Histórico.

Contexto.

Versionamento.

Quando uma IA gera uma alteração, ela precisa ser rastreável.

Quem alterou?

Quando?

Por quê?

Qual problema resolveu?

Git responde todas essas perguntas.


Git no universo IBM Mainframe

Durante muitos anos o desenvolvimento Mainframe utilizou ferramentas como:

  • Endevor

  • Changeman

  • Librarian

  • Panvalet

Hoje muitas empresas estão integrando esses ambientes ao Git.

Isso permite:

  • CI/CD

  • Pull Requests

  • Code Review

  • Integração com Jenkins

  • GitHub Actions

  • Azure DevOps

  • IBM Dependency Based Build (DBB)

  • Zowe CLI

  • VS Code

  • OpenShift

  • Ansible

O código COBOL continua executando no IBM Z, mas o ciclo de desenvolvimento passa a seguir práticas modernas de engenharia de software.


Git para um COBOL Padawan

Se você está iniciando na programação COBOL, encare o Git como uma habilidade tão importante quanto aprender:

  • IF

  • PERFORM

  • EVALUATE

  • READ

  • WRITE

  • EXEC SQL

  • CICS LINK

Hoje um profissional que domina apenas a linguagem perde competitividade.

As empresas procuram desenvolvedores que também entendam de colaboração, automação, revisão de código e integração contínua.


Boas práticas para o dia a dia

Algumas recomendações fazem enorme diferença:

  • Faça commits pequenos e frequentes.

  • Cada commit deve representar uma única alteração lógica.

  • Escreva mensagens claras e objetivas.

  • Nunca desenvolva diretamente na branch main.

  • Revise as mudanças com git diff antes de cada commit.

  • Consulte git status constantemente.

  • Configure um .gitignore adequado ao seu projeto.

  • Prefira git fetch quando quiser analisar alterações antes de integrá-las.

  • Evite git reset --hard sem compreender totalmente suas consequências.

  • Utilize Pull Requests para revisão de código e compartilhamento de conhecimento.


Conclusão

O Git é muito mais do que uma coleção de comandos. Ele representa uma mudança de paradigma na forma como construímos software, promovendo colaboração, rastreabilidade e segurança. Para o programador COBOL Padawan, dominar essa ferramenta significa conectar décadas de experiência em sistemas corporativos às práticas modernas de DevOps, integração contínua e desenvolvimento assistido por Inteligência Artificial.

Assim como aprender JCL vai muito além de decorar //JOB e //EXEC, aprender Git vai muito além de executar git add, git commit e git push. O verdadeiro diferencial está em compreender sua arquitetura interna, seus objetos, seus fluxos de trabalho e a filosofia que sustenta um dos projetos de software mais influentes da história.

No universo Bellacosa Mainframe, o Git não substitui a disciplina que sempre caracterizou o desenvolvimento em IBM Z — ele a amplia. Ele oferece mecanismos para preservar conhecimento, facilitar auditorias, permitir revisões estruturadas e integrar aplicações legadas a pipelines modernas de entrega contínua. Em uma era em que a Inteligência Artificial acelera a escrita de código, o Git continua sendo a memória confiável do projeto, registrando cada decisão técnica e garantindo que a evolução do software seja transparente, reproduzível e segura.

O conselho final para todo COBOL Padawan é simples: não estude apenas os comandos. Estude os conceitos. Entenda como o Git pensa. Quando isso acontecer, você deixará de ser apenas um usuário da ferramenta e passará a utilizá-la como um verdadeiro engenheiro de software, preparado para atuar tanto em aplicações modernas quanto nos ambientes críticos que movimentam bancos, seguradoras, governos e grandes corporações ao redor do mundo. Afinal, tecnologias mudam, linguagens evoluem, mas a capacidade de controlar, compreender e colaborar sobre o código continuará sendo uma das competências mais valiosas da engenharia de software.

Vagner Renato Bellacosa, IBM Champion e especialista em IBM Mainframe
IBM Z17 SYSTEM ONLINE
Sobre o autor

Vagner Renato Bellacosa

IBM Champion 2026 • Especialista em IBM Mainframe

Vagner Renato Bellacosa trabalha com IBM Mainframe desde 1988 , é IBM Champion e especialista em COBOL, CICS, Db2, z/OS e IBM Z. Compartilha experiências profissionais, conhecimento técnico, história da computação e práticas do universo mainframe para aproximar novas gerações das tecnologias que sustentam empresas, bancos e governos ao redor do mundo.

IBM Champion IBM Z COBOL CICS Db2 z/OS Mainframe desde 1988
GitHub LinkedIn
Inicializando conteúdo...