☕ Um Café no Bellacosa Mainframe
Gostou do conteúdo? Ajude a manter o café quente, o COBOL compilando e o mainframe acordado. 😄
☕ Pague um café ao Bellacosa

Translate

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

segunda-feira, 7 de setembro de 2026

O Manual da Guilda do Programador Mainframe — Do Rank F ao Rank S

 
Bellacosa Mainframe e o manual para um dev programador cobol iniciante nas artes secretas do mainframe

Um Café no Bellacosa Mainframe

O Manual da Guilda do Programador Mainframe — Do Rank F ao Rank S

Ou: como COBOL, JCL, Db2, CICS, RACF, dumps, documentação, café, S0C7, SQLCODE -911, ICH408I, Technical Debt, Deadline e o Demon Lord Boleto transformaram uma carreira de TI no RPG mais longo que você jamais instalou

Existe um momento inesquecível na vida de todo programador mainframe.

Você recebe seu primeiro USERID.

Alguém lhe entrega uma senha temporária.

Você acessa uma tela preta.

No alto aparece algo que parece ter sido construído numa civilização anterior à invenção do mouse.

Você olha aquilo.

Aquilo olha para você.

Parabéns.

Você acaba de entrar na:


GUILDA DOS PROGRAMADORES MAINFRAME

Seu Rank atual:

F

Sua classe:

Novato

Experiência:

0 XP

Equipamento:

  • um notebook corporativo;

  • um USERID recém-criado;

  • uma senha que expirará no pior momento possível;

  • três PDFs;

  • acesso limitado;

  • nenhum conhecimento sobre produção;

  • uma caneca de café.

Sua primeira quest aparece:

ALTERE UMA MENSAGEM NUM PROGRAMA COBOL.

Dificuldade estimada:

Dificuldade percebida pelo novato:

⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

Você ainda não sabe, mas acabou de iniciar um dos RPGs profissionais mais longos existentes.

Não existe tela de Game Over.

Existe:

ABEND



1. Antes de começar: escolha sua classe

Nos RPGs tradicionais escolhemos Warrior, Mage, Cleric ou Rogue.

No Mainframe RPG também existem classes.

COBOL Developer — Warrior

Ataca problemas diretamente.

Sua arma principal é:

IF
   ...
ELSE
   ...
END-IF

Possui resistência extraordinária a sistemas com quarenta anos.

Fraqueza natural:

dados inválidos.


Db2 Specialist — Mage

Manipula entidades invisíveis chamadas tabelas, índices, packages e access paths.

Seu feitiço favorito:

SELECT

Seu feitiço proibido:

DELETE FROM TABELA;

sem WHERE.

Quando isso acontece, nem resurrection spell resolve facilmente.


CICS Specialist — Rogue

Extremamente rápido.

Trabalha em milissegundos.

Conhece transações, regions e resources.

Seu inimigo natural é alguém dizendo:

“CICS está lento.”

Sem fornecer nenhuma outra informação.


RACF Administrator — Paladin

Guardião das portas.

Decide quem entra.

Quem lê.

Quem altera.

Quem executa.

Seu poder supremo é dizer:

ACCESS DENIED.

Não importa se você é diretor, gerente, arquiteto ou primo do CEO.


System Programmer — Archmage

Classe misteriosa.

Habita regiões profundas do reino chamadas PARMLIB, PROCLIB e SYS1.

Fala palavras como:

IPL.

APF.

LPA.

SVC.

SMF.

WLM.

SMP/E.

Quando entra numa War Room, todos ficam um pouco mais tranquilos.

Ou mais preocupados.

Depende da expressão dele.



2. Rank F — O Novato

Você começa no Rank F.

Não sabe quase nada.

E isso é perfeitamente normal.

Seu primeiro grande aprendizado é descobrir que não saber não é um defeito inicial: é o estado padrão da profissão.

Quests do Rank F

  • acessar TSO/ISPF;

  • navegar entre datasets;

  • entender PDS e membros;

  • editar um programa COBOL;

  • compilar;

  • executar um JOB;

  • consultar SDSF;

  • descobrir por que o JOB não terminou;

  • aprender a diferença entre erro de compilação e ABEND;

  • entender que produção não é lugar para experiências criativas.

Equipamento inicial

Espada COBOL +1

Escudo JCL +1

Mapa ISPF +2

Poção Café +5 concentração

Pergaminho “Manual da Empresa” +10 confusão

Skill especial

ASK SENIOR

Cooldown:

depende do humor do senior.

É provavelmente a skill mais importante dessa fase.



3. O primeiro monstro: JCL ERROR

Você submete seu primeiro JOB.

Espera.

Nada.

Olha novamente.

Descobre uma mensagem.

O coração acelera.

Você pensa:

“Quebrei o mainframe.”

Não.

Provavelmente esqueceu uma vírgula.

Mas essa primeira batalha ensina uma regra fundamental:

Leia a mensagem de erro.

Parece óbvio.

Não é.

Programadores frequentemente passam vinte minutos imaginando teorias sofisticadas enquanto o sistema está dizendo exatamente o problema.

O aventureiro experiente aprende:

Primeiro leia o que o monstro escreveu.

Depois desembainhe a espada.



4. Rank E — Junior

Depois de algumas quests você sobe para Rank E.

Agora consegue fazer pequenas alterações sem supervisão constante.

Isso produz um fenômeno perigoso:

confiança.

Você começa a achar que entende o sistema.

O sistema percebe.

E envia seu primeiro boss.

S0C7


5. Boss #1 — S0C7, o Devorador de Dados

Você executa o programa.

Ele morre.

Na tela:

S0C7

O novato pergunta:

— O que significa?

O veterano responde:

— Data Exception.

Tradução RPG:

Você tentou tratar alguma coisa como número e aquilo discordou.

Talvez um campo numérico contenha dados inválidos.

Talvez exista problema de definição.

Talvez um movimento tenha colocado conteúdo inesperado numa área.

A batalha começa.

Armas contra S0C7

  • dump;

  • offset;

  • listing;

  • compile options;

  • análise dos dados;

  • conhecimento das PICs;

  • atenção.

XP recebido

+350 DEBUGGING

Achievement desbloqueado

“Meu primeiro ABEND.”

Todo programador mainframe deveria receber um badge por isso.


6. Rank D — Pleno em formação

Agora você começa a compreender que programa nenhum vive sozinho.

Seu COBOL conversa com:

Db2.

VSAM.

CICS.

MQ.

Arquivos.

Outros programas.

Jobs.

APIs.

Usuários.

E processos de negócio criados antes de você entrar na empresa.

Você acaba de desbloquear:

DEPENDENCY HELL

A dungeon aumentou.


7. A Party

Nenhum aventureiro sensato entra sozinho numa dungeon perigosa.

No mainframe também não deveria.

Sua party pode possuir:

COBOL Developer

Ataca o código.

DBA

Controla os dragões relacionais.

System Programmer

Manipula as forças fundamentais do z/OS.

Security Specialist

Possui as chaves do castelo.

Production Control

Conhece horários e dependências.

Business Analyst

Traduz a misteriosa linguagem dos usuários.

Support

Sabe onde os cadáveres estão enterrados.

A grande skill profissional aparece quando você percebe:

não precisa saber tudo; precisa saber quem sabe.

Isso vale mais XP do que decorar centenas de comandos.


8. Boss #2 — SQLCODE -911, o Senhor dos Locks

Você escreve SQL.

Testa.

Funciona.

Produção chega.

Então:

SQLCODE = -911

O monstro apareceu.

Rollback.

Deadlock.

Timeout.

Seu programa estava disputando recursos com outra coisa.

Você descobre que bancos de dados não são bibliotecas silenciosas.

São cidades.

Centenas ou milhares de transações querem acessar recursos simultaneamente.

Algumas leem.

Outras alteram.

Algumas seguram locks.

Outras esperam.

Até que Db2 olha para a situação e decide:

“Alguém precisa morrer.”

Parabéns.

Foi sua transação.

Skills necessárias

  • compreender COMMIT;

  • entender ROLLBACK;

  • conhecer locking;

  • investigar concorrência;

  • analisar tempo de transação;

  • compreender access paths;

  • conversar com DBA.

XP

+750 CONCURRENCY

Loot

Anel do COMMIT Frequente

Use com sabedoria.

Commit demais também pode trazer problemas.


9. Rank C — O profissional que começa a enxergar o sistema

Aqui ocorre uma transformação importante.

Você deixa de perguntar apenas:

“Onde está o erro?”

E começa a perguntar:

“Por que esse erro aconteceu?”

Essa mudança parece pequena.

Não é.

É a passagem de executor para analista.

O Rank F corrige o registro.

O Rank C pergunta quem gerou o registro errado.

O Rank F reinicia o JOB.

O Rank C pergunta por que ele falhou.

O Rank F libera espaço.

O Rank C pergunta por que o crescimento não foi previsto.

Você começa a combater causas, não apenas sintomas.


10. Boss #3 — ICH408I, o Guardião das Portas

Você executa alguma coisa.

Recebe:

ICH408I

Você tenta novamente.

ICH408I

Mais uma vez.

ICH408I

O RACF não muda de opinião porque você clicou três vezes.

Esse boss ensina uma das regras fundamentais de segurança:

autenticação não significa autorização.

Você conseguiu entrar no reino.

Isso não significa que pode abrir todas as portas.

Talvez seu USERID não tenha acesso.

Talvez o grupo esteja incorreto.

Talvez o perfil proteja o recurso.

Talvez você precise de READ.

UPDATE.

CONTROL.

ALTER.

E talvez você não devesse receber nenhum deles.

Arma recomendada

Não é:

“Me dê ALTER em tudo.”

A arma correta chama-se:

Least Privilege.

XP

+900 SECURITY

Achievement

“RACF disse não.”


11. Equipamentos raros

Com o tempo você começa a colecionar equipamentos.

Não são espadas.

São ferramentas.

Debugger

Item raro.

Permite observar o monstro antes que ele mate seu programa.

Git

Inventário dimensional.

Guarda versões anteriores das suas armas.

Pipeline CI/CD

Esteira mágica que transporta artefatos entre reinos.

Monitoramento

Olho de Sauron corporativo.

Idealmente usado para observar sistemas, não hobbits.

Logs

Pergaminhos proféticos.

Quase sempre possuem pistas.

Documentação

Item lendário.

Extremamente poderoso.

Raramente atualizado.


12. Rank B — Senior

Aqui surge uma coisa curiosa.

Você sabe muito mais.

Mas começa a dizer:

“Depende.”

O junior acha isso frustrante.

Ele pergunta:

— Qual é a melhor solução?

Senior:

— Depende.

— Qual banco devemos usar?

— Depende.

— Devemos fazer COMMIT aqui?

— Depende.

— Podemos colocar isso em produção?

O senior olha fixamente.

Depende muito.

Isso não é indecisão.

É percepção de contexto.

Quanto mais você aprende, mais percebe quantas variáveis existem.


13. Boss #4 — Deadline, o Senhor do Tempo

Nenhum treinamento prepara adequadamente para esse monstro.

Deadline possui habilidade especial:

TIME COMPRESSION

Projeto de seis meses.

Prazo:

três meses.

Depois:

dois.

Então alguém pergunta:

“Conseguimos entregar sexta?”

Você olha o calendário.

Hoje é quinta.

Ataques do Deadline

  • reunião de status;

  • daily adicional;

  • planilha vermelha;

  • “quick win”;

  • “só falta um detalhe”;

  • mudança de requisito;

  • reunião para discutir por que existem tantas reuniões.

Defesa

  • estimativa realista;

  • priorização;

  • gerenciamento de risco;

  • documentação;

  • comunicação;

  • coragem profissional para dizer:

“Não.”

Essa última é uma skill Rank A.


14. Boss #5 — Technical Debt, o Monstro que Alimentamos

Esse é diferente.

Ele não aparece repentinamente.

Nós o criamos.

Começa pequeno.

“Depois corrigimos.”

“É temporário.”

“Só para entrar em produção.”

“Na próxima release melhoramos.”

Cada frase adiciona HP ao monstro.

Cinco anos depois existe uma rotina de 8.000 linhas que ninguém quer tocar.

O comentário diz:

* TEMPORARIO - NAO REMOVER
* 2007

Estamos em 2026.

O temporário completou dezenove anos.

Pode votar.

😂

Technical Debt Level 80

Ataques:

  • manutenção cara;

  • regressões;

  • medo de mudança;

  • conhecimento concentrado;

  • documentação inexistente;

  • dependências misteriosas.

Fraqueza

Refactoring controlado.

Testes.

Documentação.

Automação.

Tempo.

Naturalmente, o Deadline Boss geralmente impede que você use essas armas.

Os dois trabalham juntos.


15. Rank A — Especialista

O especialista não é necessariamente quem conhece mais comandos.

É quem possui profundidade suficiente para compreender consequências.

Ele começa a enxergar sistemas como ecossistemas.

Uma alteração COBOL pode afetar Db2.

Db2 pode alterar tempo de resposta.

Tempo de resposta pode afetar CICS.

CICS pode afetar usuários.

Usuários podem afetar faturamento.

Faturamento pode afetar diretoria.

Diretoria pode afetar você.

Tudo está conectado.

Skill desbloqueada

SYSTEM THINKING +100


16. A Skill lendária: reconhecer padrões

Um jovem olha um incidente e vê:

ERROR

O especialista olha e pensa:

“Já vi algo parecido.”

Não exatamente aquilo.

Mas algo parecido.

Essa biblioteca mental foi construída durante milhares de horas.

Incidentes.

Projetos.

Erros.

Migrações.

Falhas.

Sucessos.

Madrugadas.

É uma espécie de machine learning biológico.

Dataset:

sua carreira.

Treinamento:

vinte anos.

Inference:

“Olha aquele job primeiro.”


17. O sorriso ninja

Então aparece uma ferramenta nova.

Nova release.

Interface redesenhada.

Cloud.

API.

IDE.

Pipeline.

Você nunca utilizou exatamente aquela versão.

Cliente pergunta:

— Você sabe fazer?

Você:

😎

— Sei.

Internamente:

🦋🦋🦋🦋

O que você realmente quis dizer foi:

“Conheço suficientemente bem esse tipo de problema para descobrir como essa versão resolveu mudar tudo.”

Isso não é necessariamente blefe.

É confiança na capacidade de aprender.

A skill chama-se:

RELEARN

Rank:

S


18. Rank S — Mestre da Guilda

Pouquíssimos chegam aqui no sentido verdadeiro.

Não é determinado por idade.

Nem apenas por certificações.

Rank S aparece quando conhecimento técnico, experiência, contexto, comunicação e capacidade de formar outras pessoas começam a trabalhar juntos.

O Mestre da Guilda não precisa resolver tudo pessoalmente.

Ele sabe organizar a batalha.

Pergunta:

— O que mudou?

— Quando começou?

— Qual impacto?

— Conseguimos reproduzir?

— Temos rollback?

— Quem conhece esse componente?

— Quais evidências temos?

Observe.

Nenhuma magia.

Somente método.


19. A árvore de Skills

Depois de muitos anos, uma árvore possível poderia parecer assim:

PROGRAMADOR MAINFRAME
│
├── COBOL
│   ├── Estruturas
│   ├── Arquivos
│   ├── Debugging
│   └── Performance
│
├── JCL
│   ├── JOB
│   ├── EXEC
│   ├── DD
│   └── Utilities
│
├── DATA
│   ├── VSAM
│   ├── Db2
│   └── IMS
│
├── ONLINE
│   └── CICS
│
├── INTEGRATION
│   ├── MQ
│   ├── APIs
│   └── z/OS Connect
│
├── SECURITY
│   └── RACF
│
├── DEVOPS
│   ├── Git
│   ├── CI/CD
│   └── Automation
│
└── VETERAN SKILLS
    ├── Debugging
    ├── Comunicação
    ├── Contexto
    ├── Mentoria
    ├── Pattern Recognition
    └── Relearn

A última árvore costuma ser a mais difícil.

Não existe curso de quatro horas para obter vinte anos de contexto.


20. Como ganhar XP de verdade

Nem todo XP vem de certificação.

Alguns dos maiores ganhos acontecem quando algo dá errado.

Quest: corrigir primeiro ABEND

+500 XP

Quest: resolver incidente em produção

+1.000 XP

Quest: admitir que sua alteração causou o incidente

+2.000 XP

Quest: documentar para ninguém repetir

+3.000 XP

Quest: ensinar um junior

+5.000 XP

Quest: impedir um incidente antes que aconteça

+10.000 XP

Curiosamente, essa última geralmente não recebe reconhecimento.

Porque nada aconteceu.

Esse é o paradoxo do bom profissional de infraestrutura.


21. Side quests

Durante sua carreira aparecem missões secundárias.

“Aprenda Python.”

“Conheça Cloud.”

“Faça certificação.”

“Estude APIs.”

“Aprenda Git.”

“Agora containers.”

“Agora IA.”

Você abre seu mapa.

Existem 847 quests pendentes.

E apenas 24 horas por dia.

Então desbloqueia uma habilidade fundamental:

SELECT QUEST

Não tente aprender tudo.

Escolha aquilo que aproxima você de algum objetivo.

Senão você passará a vida coletando XP sem terminar a campanha principal.


22. O item mais raro: Tempo

Dinheiro compra livros.

Cursos.

Computadores.

Certificações.

Mas existe um recurso que não pode ser farmado:

tempo.

Um curso gratuito de quarenta horas custa quarenta horas.

Talvez valha.

Talvez não.

O aventureiro Rank S aprende a perguntar:

“Este conhecimento vale o tempo necessário para adquiri-lo?”

Porque cada curso compete com trabalho, descanso, família, leitura, caminhada...

e anime.

Nunca esqueçamos o anime.


23. O chefão secreto: Síndrome do Impostor

Mesmo depois de milhares de XP aparece uma criatura invisível.

Ela sussurra:

“Você não sabe o suficiente.”

Tecnicamente ela está correta.

Ninguém sabe.

O problema está na conclusão seguinte:

“Portanto você não deveria estar aqui.”

Errado.

O especialista não é aquele que sabe tudo.

É aquele que desenvolveu métodos para lidar com aquilo que não sabe.

Essa distinção salva carreiras.


24. O Boss final

Depois de COBOL.

Depois de Db2.

Depois de CICS.

Depois de RACF.

Depois do S0C7.

Depois do -911.

Depois do ICH408I.

Depois do Deadline.

Depois do Technical Debt.

Você acredita estar preparado.

Então o céu escurece.

A música muda.

Surge uma criatura gigantesca.

HP:

Resistência:

100%

Respawn:

MENSAL

Nome:

BOLETO

O Demon Lord definitivo.


25. Boleto — Level 99

Você pode trocar de emprego.

Boleto acompanha.

Pode virar freelancer.

Ele encontra você.

Pode tornar-se consultor.

Ele escala junto.

Pode tirar férias.

Ele sabe onde você mora.

Sua habilidade suprema chama-se:

VENCIMENTO

Todo mês ele retorna.

Isso explica boa parte da economia da Guilda.

O aventureiro veterano pensa:

“Talvez eu pare de aceitar projetos.”

Boleto:

“Interessante.”

😂

E imediatamente aparece no LinkedIn:

COBOL/Db2 Senior Consultant — Immediate Start — 6 months.

O velho aventureiro olha para a espada pendurada na parede.

Suspira.

— Uma última quest.

Boleto sorri.

Ele já ouviu isso antes.


26. New Game+

Existe, porém, uma fase curiosa da carreira.

Depois de acumular conhecimento suficiente, você começa a ensinar.

E ensinar é uma espécie de:

NEW GAME+

Você retorna às primeiras dungeons.

Só que agora acompanha novos aventureiros.

O junior pergunta:

— O que é S0C7?

Você sorri.

Lembra do seu primeiro.

Explica.

Ele resolve.

Ganha XP.

E alguma coisa interessante acontece.

Você também ganha.

Porque ensinar força a organizar aquilo que anos de experiência deixaram intuitivo.

Talvez essa seja uma das formas mais bonitas de veterania.

Transformar cicatrizes em mapas para quem vem depois.


27. Easter Egg — o verdadeiro Rank S

Existe um segredo escondido neste manual.

Rank S não significa:

Super Senior.

Significa:

Sobrevivente.

Sobreviveu às mudanças.

Às releases.

Aos projetos.

Aos incidentes.

Às tecnologias “que acabariam com o mainframe”.

Às reorganizações.

Às ferramentas revolucionárias.

Às interfaces redesenhadas.

Às certificações.

Ao Ceifeiro Silencioso.

Ao Deadline.

Ao Technical Debt.

E, até agora...

ao Boleto.

Mas sobretudo sobreviveu sem perder completamente uma coisa:

curiosidade.

Porque quando a curiosidade morre, estudar vira apenas obrigação.

E uma carreira tecnológica sem vontade de descobrir coisas novas transforma cada atualização numa punição.


28. A regra de ouro da Guilda

Se eu tivesse que entregar somente uma regra ao programador começando hoje, seria:

Aprenda fundamentos profundamente e ferramentas suficientemente.

Ferramentas mudam.

Interfaces mudam.

Versões desaparecem.

Menus migram.

Produtos são renomeados.

Mas compreender transações, dados, concorrência, segurança, arquitetura, debugging e sistemas continuará permitindo que você reconheça os mesmos monstros usando roupas diferentes.

O goblin de 1998 pode aparecer em 2027 com Kubernetes, API REST e inteligência artificial.

Continua sendo goblin.

Só ganhou marketing.


Epílogo — A próxima quest

03:17.

Telefone toca.

Produção está parada.

Um jovem Rank F olha assustado para o terminal.

Ao lado dele existe um veterano Rank S.

— O que faço?

O veterano coloca a caneca de café sobre a mesa.

— Primeiro, não faça nada.

— Como assim?

— Leia.

Eles olham os logs.

O jovem encontra uma mensagem:

ICH408I

— RACF?

O veterano sorri.

— Talvez.

— Você não sabe?

— Ainda não.

O jovem estranha.

Aquele homem possui décadas de experiência.

Como pode responder “não sei”?

O veterano continua:

— Vamos descobrir.

Nesse instante o jovem aprende uma coisa muito maior do que RACF.

Descobre o verdadeiro significado de experiência.

Não é possuir todas as respostas.

É não precisar fingir que possui.

É saber investigar.

Saber testar.

Saber pedir ajuda.

Saber voltar atrás.

Saber diferenciar evidência de palpite.

Saber quando agir.

E, talvez ainda mais importante...

saber quando não agir.

Alguns minutos depois encontram a causa.

04:02.

Produção retorna.

O jovem sorri.

QUEST COMPLETE

+1.000 XP

SKILL UNLOCKED: INCIDENT ANALYSIS

Ele pergunta:

— Um dia chego ao Rank S?

O veterano pega novamente o café.

— Se continuar estudando.

— Só isso?

— Não.

— Trabalhando?

— Também.

— Então como?

O veterano olha para a enorme sala de máquinas.

COBOL continuará executando.

Db2 continuará protegendo dados.

CICS continuará processando transações.

RACF continuará dizendo não.

S0C7 continuará encontrando campos impossíveis.

SQLCODE -911 continuará lembrando que ninguém trabalha sozinho.

Deadline continuará correndo.

Technical Debt continuará crescendo escondido.

Novas ferramentas chegarão.

Interfaces serão redesenhadas.

E o Boleto...

Bem.

O Boleto jamais será descontinuado.

Ele coloca a mão no ombro do novato.

— Continue entrando nas dungeons.

— Mesmo com medo?

O veterano abre o famoso sorriso ninja.

😎

— Principalmente quando houver algumas borboletas.

O jovem olha novamente para o terminal.

No canto inferior aparece:

READY

A próxima quest já está esperando.

Um Café no Bellacosa Mainframe

Mesmos sistemas. Novas histórias. Sempre um bom café.

Ficha final do personagem

Classe: Programador Mainframe
Rank inicial: F
Rank máximo: S
Arma: Conhecimento
Escudo: Experiência
Poção: Café
Mapa: Documentação
Party: Equipe
Skill lendária: Reaprender
Fraqueza: “É só uma alteraçãozinha”
Boss recorrente: Deadline
Boss ancestral: Technical Debt
Demon Lord: Boleto
Achievement final: Ainda curioso depois de décadas
Próxima missão: READY >

Para saber mais

https://eljefemidnightlunch.blogspot.com/2026/09/a-guilda-dos-aventureiros-mainframe-por.html



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. ☕🔥

quinta-feira, 12 de setembro de 2024

Kojak Entra no CPD — O Dia em que um SQLCODE -911 Virou Suspeito e o Db2 Foi Chamado para Depor

 

Bellacosa Mainframe apresenta cobol e db2

☕ Um Café no Bellacosa Mainframe

Kojak Entra no CPD — O Dia em que um SQLCODE -911 Virou Suspeito e o Db2 Foi Chamado para Depor

Ou: como COBOL, SQL, DBRM, BIND, PACKAGE, access path, COMMIT, ROLLBACK, locking, CICS e um programador iniciante descobriram que, no mainframe, até um SELECT tem antecedentes

Nova York, 1973.

Um policial careca, impecavelmente vestido, andando pelas ruas com um pirulito na boca começa a resolver crimes enquanto solta ironias e uma pergunta que se tornaria inseparável do personagem:

“Who loves ya, baby?”

Era o tenente Theo Kojak.

A série Kojak, criada por Abby Mann e protagonizada por Telly Savalas, estreou na CBS em 24 de outubro de 1973 e permaneceu originalmente no ar até 1978. (Paramount Press Express)

Curiosamente, Kojak surgiu antes da série: Telly Savalas interpretou o personagem no telefilme The Marcus-Nelson Murders, de 1973, que funcionou como origem do programa. (Los Angeles Times)

E existe algo profundamente mainframe em Kojak.

Ele não olha apenas para o cadáver.

Olha para quem entrou, quem saiu, quem tinha autorização, quem estava segurando o recurso, quem alterou o registro e por que aquela história aparentemente perfeita não combina com as evidências.

Troque a delegacia por um CPD.

Troque o assassinato por uma transação travada.

Troque as testemunhas por logs.

E dê ao tenente um terminal 3270.

Temos nosso novo investigador Db2.



Prólogo — 03:17, alguma coisa morreu em produção

O telefone toca.

O programador COBOL iniciante atende.

— Produção está parada.

Cinco palavras capazes de transformar café em combustível nuclear.

Ele abre o fonte.

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE NUMERO = :WS-CONTA
END-EXEC.

Olha novamente.

Nada parece errado.

Compilou.

Ontem funcionava.

O programador conclui:

— Deve ser o banco.

A porta do CPD abre.

Um homem careca entra lentamente, coloca um pirulito na boca e observa o terminal.

— O banco, baby?

Silêncio.

— Vamos começar novamente. Quem executou o SQL?

E aí descobrimos nosso primeiro problema.



1. COBOL não executa SQL sozinho

Quando vemos:

EXEC SQL
    SELECT ...
END-EXEC

é fácil imaginar que SELECT seja uma instrução COBOL.

Não é.

COBOL e SQL são linguagens diferentes trabalhando juntas.

Podemos imaginar três responsabilidades:

COBOL
   │
   ├── lógica da aplicação
   ├── cálculos
   ├── decisões
   └── fluxo
          │
          ▼
         SQL
          │
          └── declara quais dados queremos
                    │
                    ▼
                   Db2
                    │
                    └── determina como obtê-los

O COBOL pode dizer:

“Preciso consultar o saldo desta conta.”

O SQL expressa:

SELECT SALDO
FROM CONTA
WHERE NUMERO = :WS-CONTA

E o Db2 precisa resolver como encontrar aquele registro eficientemente.

Kojak tira o pirulito da boca.

— Então temos três testemunhas. COBOL diz uma coisa, SQL pede outra e Db2 faz o trabalho pesado.

Exatamente.



2. O primeiro interrogatório: as Host Variables

Observe:

WHERE NUMERO = :WS-CONTA

Por que existe aquele :?

Porque WS-CONTA pertence ao programa hospedeiro.

É uma host variable.

Temos uma fronteira:

       COBOL                     SQL

    WS-CONTA ───────────────► :WS-CONTA

    WS-SALDO ◄─────────────── :WS-SALDO

No comando:

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE NUMERO = :WS-CONTA
END-EXEC

WS-CONTA fornece informação.

WS-SALDO recebe informação.

Parece simples.

Até aparecerem:

  • tipos incompatíveis;

  • valores NULL;

  • indicator variables;

  • truncamentos;

  • conversões;

  • nenhuma linha;

  • múltiplas linhas.

Kojak aponta para WS-CONTA.

— Interrogue esse sujeito primeiro. Todo mundo culpa o Db2 antes de perguntar o que mandou para ele.

Primeira regra da investigação:

entrada errada produz investigação errada.


3. O crime aconteceu antes da execução

Nosso iniciante acredita que o fonte vai diretamente para o compilador COBOL.

Kojak balança a cabeça.

— Baby... tem alguém faltando nessa história.

Quando existe SQL embutido, o SQL precisa ser processado.

No fluxo tradicional, podemos representar:

COBOL + SQL
     │
     ▼
PRECOMPILE
     │
     ├────────────► DBRM
     │
     ▼
COBOL modificado
     │
     ▼
COBOL COMPILER
     │
     ▼
OBJECT
     │
     ▼
LINK-EDIT
     │
     ▼
LOAD MODULE

O processamento SQL e o processamento COBOL são coisas distintas.

E acabamos de encontrar nosso primeiro suspeito misterioso.

DBRM.


4. DBRM — o dossiê policial do SQL

DBRM significa Database Request Module.

Não é o executável COBOL.

Não é a tabela.

Não é o banco.

Não é o programa completo.

Uma maneira didática de imaginá-lo é como o dossiê contendo informações sobre as requisições SQL extraídas do programa para uso posterior pelo Db2.

A documentação IBM descreve o DBRM dentro justamente desse processo de preparação das instruções SQL para o bind. (Wikipedia)

Imagine:

PROGRAMA ABC123

SQL 001
SELECT SALDO...

SQL 002
UPDATE CONTA...

SQL 003
INSERT MOVIMENTO...

O Db2 precisará conhecer essas requisições.

O DBRM entra nessa história.

Kojak pega a pasta.

— Agora temos antecedentes.


5. BIND — agora leve o suspeito para a delegacia

Aqui aparece uma palavra que todo programador COBOL/Db2 precisa conhecer:

BIND.

Simplificando bastante, durante o bind o Db2 trabalha com as informações SQL preparadas anteriormente e produz aquilo que será necessário para executar o SQL estático.

Temos:

DBRM
  │
  ▼
BIND PACKAGE
  │
  ▼
PACKAGE

Agora nossa investigação começa a ficar interessante.

Porque significa que existem dois universos relacionados:

             APLICAÇÃO

        ┌───────────────┐
        │               │
        ▼               ▼
      COBOL            SQL
        │               │
        ▼               ▼
 LOAD MODULE          DBRM
                        │
                        ▼
                      BIND
                        │
                        ▼
                     PACKAGE

É perfeitamente possível que alguém diga:

“Mas o COBOL compilou!”

Ótimo.

Isso prova apenas uma parte da história.

Kojak sorri.

— Compilou? Muito bonito. Agora me mostre o package.


6. PACKAGE — o personagem que o iniciante quase nunca conhece

O package contém informações necessárias para a execução das instruções SQL estáticas associadas à aplicação.

E aqui ocorre uma mudança mental importante.

O programa executável e o SQL preparado possuem processos relacionados, mas distintos.

Portanto:

SOURCE
  │
  ├──────── COBOL ────────► LOAD MODULE
  │
  └──────── SQL ─► DBRM ─► BIND ─► PACKAGE

Na execução, esses mundos precisam conversar corretamente.

É por isso que um problema de Db2 pode existir mesmo quando o compilador COBOL não reclamou.

O compilador não é Sherlock Holmes.

Muito menos Kojak.


7. “Mas quem decidiu usar aquele índice?”

Chegamos ao grande interrogatório.

Considere:

SELECT NOME,
       LIMITE,
       SALDO
FROM CLIENTE
WHERE CPF = :WS-CPF

O programador declarou o que deseja.

Não escreveu:

vá para cilindro X
abra página Y
ande 37 posições
leia registro Z

Essa é uma das grandes diferenças entre programação procedural e acesso relacional.

O Db2 possui um optimizer.

Conceitualmente:

             SQL
              │
              ▼
          OPTIMIZER
              │
       ┌──────┼──────┐
       │      │      │
       ▼      ▼      ▼
   índices estatísticas cardinalidade
       │      │      │
       └──────┼──────┘
              ▼
         ACCESS PATH
              │
              ▼
          EXECUÇÃO

O optimizer avalia alternativas e custos.

Pode considerar índices.

Pode considerar outras estratégias.

O resultado dessa decisão é fundamental para performance.

Kojak olha para o programador:

— Você escreveu o SELECT. Mas não decidiu necessariamente como ele encontraria o sujeito.

Perfeito.


8. RUNSTATS — quando a testemunha está dizendo a verdade de 2019

Agora temos uma situação deliciosa.

O programa não mudou.

O SQL não mudou.

A tabela não mudou estruturalmente.

Mas o desempenho ficou horrível.

Como?

Imagine que o Db2 esteja tomando decisões baseado em informações estatísticas inadequadas ou desatualizadas.

É como Kojak perguntar:

— Quantas pessoas vivem neste prédio?

E alguém responder:

— Doze.

— Quando você contou?

— Em 1997.

Temos um problema.

As estatísticas ajudam o optimizer a compreender características dos dados.

Daí a importância de operações como RUNSTATS.

Isso nos ensina uma lição extraordinária:

Performance SQL não está inteiramente dentro do fonte SQL.

Ela depende do ecossistema.


9. Índice não é pó mágico

O iniciante aprende:

Índice deixa SELECT rápido.

Depois cria índice para tudo.

Parabéns.

Acabamos de transformar uma boa ideia em um novo incidente.

Índices possuem custo.

Precisam ser mantidos.

INSERT, UPDATE e DELETE podem ter trabalho adicional quando índices associados precisam ser atualizados.

Portanto:

MAIS ÍNDICES

      não significa automaticamente

MAIS PERFORMANCE

A pergunta é:

qual índice atende quais padrões reais de acesso?

Kojak provavelmente perguntaria:

— Esse índice estava onde na noite do crime?


10. O SQLCODE chega para depor

Executamos:

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE NUMERO = :WS-CONTA
END-EXEC

E agora?

Precisamos saber o resultado.

Entra o SQLCODE.

Didaticamente:

SQLCODE = 0
     │
     └── sucesso

SQLCODE positivo
     │
     └── condição/warning

SQLCODE negativo
     │
     └── erro

Um programador iniciante pode fazer:

IF SQLCODE NOT = ZERO
    DISPLAY 'ERRO DB2'
END-IF.

Kojak quase engole o pirulito.

Porque os códigos precisam ser interpretados, não simplesmente classificados como “deu certo/deu errado”.

O famoso +100, por exemplo, normalmente indica ausência de linha correspondente ou fim do conjunto de resultados conforme a operação.

Isso pode ser perfeitamente normal.

Pesquisar cliente inexistente não significa necessariamente que o banco “quebrou”.


11. Até que aparece o cadáver: SQLCODE -911

Agora temos drama.

O programa retorna:

SQLCODE = -911

E alguém grita:

— Db2 caiu!

Não necessariamente.

Temos uma pista ligada a situações envolvendo rollback provocado por deadlock ou timeout, conforme o contexto e reason code.

Kojak sorri.

Finalmente um crime digno dele.

Imagine:

TRANSAÇÃO A

LOCK RECURSO 1
      │
      ▼
PRECISA RECURSO 2


TRANSAÇÃO B

LOCK RECURSO 2
      │
      ▼
PRECISA RECURSO 1

Temos:

A espera B

B espera A

Os dois poderiam esperar até a aposentadoria do programador.

O sistema precisa resolver a situação.

Bem-vindo ao mundo de locking, timeout e deadlock.


12. ACID — a divisão de crimes financeiros

Imagine uma transferência:

CONTA A = 1000
CONTA B =  500

TRANSFERÊNCIA = 100

Queremos terminar:

A = 900
B = 600

Não queremos:

A = 900
B = 500

porque o sistema caiu no meio.

É aqui que as propriedades ACID entram em cena:

Atomicity — a unidade lógica precisa ser tratada de maneira indivisível quanto ao resultado transacional.

Consistency — regras de consistência devem permanecer válidas.

Isolation — transações concorrentes precisam coexistir sob regras controladas.

Durability — depois da confirmação, os resultados precisam possuir as garantias de persistência esperadas.

Esse não é detalhe acadêmico.

É o motivo pelo qual você consegue dormir depois de transferir dinheiro pelo banco.


13. COMMIT — pode liberar os suspeitos

Considere:

UPDATE CONTA A
       │
       ▼
UPDATE CONTA B
       │
       ▼
INSERT MOVIMENTO
       │
       ▼
     COMMIT

O COMMIT delimita a confirmação apropriada daquela unidade de trabalho.

Mas imagine:

UPDATE A       OK
UPDATE B       OK
INSERT         ERRO

Dependendo da lógica e do contexto transacional, podemos precisar desfazer alterações.

Entra:

ROLLBACK

Portanto:

        UNIT OF WORK

UPDATE
   │
UPDATE
   │
INSERT
   │
   ├──── tudo correto ───► COMMIT
   │
   └──── problema ───────► ROLLBACK

Essa dupla é parte central da engenharia transacional.


14. COMMIT também é performance

Agora vem uma sutileza importante.

Alguns iniciantes imaginam COMMIT apenas como:

salvar alterações.

Mas unidades de trabalho também estão relacionadas à utilização e liberação de determinados recursos e locks.

Imagine um batch processando:

10 registros
100 registros
10.000 registros
10.000.000 registros

sem pensar adequadamente na estratégia de commit.

Ele pode manter recursos por períodos indesejáveis, afetar concorrência e complicar recuperação.

Logo, frequência de commit não deveria ser escolhida com:

COMMIT a cada 1000

simplesmente porque alguém encontrou esse número num programa de 1987.

A estratégia depende da aplicação.


15. Então chega o CICS à delegacia

Até agora poderíamos estar pensando em batch.

Mas coloque a aplicação em ambiente transacional:

CLIENTE
   │
   ▼
CICS
   │
   ▼
PROGRAMA COBOL
   │
   ▼
SQL
   │
   ▼
DB2

Agora milhares de usuários podem executar transações.

Temos simultaneamente:

CICS transaction 001 ──┐
CICS transaction 002 ──┤
CICS transaction 003 ──┼──► Db2
CICS transaction 004 ──┤
CICS transaction 005 ──┘

Nesse momento, locking deixa de ser um capítulo de apostila.

Vira sobrevivência.


16. COBOL + Db2 Connect? Cuidado com essa simplificação

O infográfico original apresenta conceitualmente uma camada intermediária chamada Db2 Connect.

Aqui Kojak levantaria uma sobrancelha.

Db2 Connect não deve ser ensinado como passagem obrigatória de todo programa COBOL local no z/OS para Db2.

Dependendo do ambiente, temos diferentes mecanismos de attachment e execução.

Batch, CICS, IMS, TSO e aplicações distribuídas podem envolver arquiteturas diferentes.

Portanto:

COBOL → DB2 Connect → Db2

não é uma representação universal.

Esse é exatamente o tipo de simplificação que funciona num infográfico 101, mas precisa ser desmontada quando o aluno chega ao nível 201.


17. “COBOL cuida da regra; Db2 cuida dos dados”

Boa explicação.

Mas incompleta.

No mundo real, Db2 também possui recursos relacionados a:

  • constraints;

  • integridade referencial;

  • views;

  • triggers;

  • stored procedures;

  • functions.

Então podemos pensar:

COBOL
 │
 ├── fluxo
 ├── cálculo
 ├── regras da aplicação
 └── orquestração

DB2
 │
 ├── persistência
 ├── integridade
 ├── concorrência
 ├── recuperação
 ├── otimização
 └── acesso relacional

As responsabilidades precisam ser projetadas.

Não simplesmente presumidas.


18. Static SQL e Dynamic SQL entram na sala

Nosso exemplo:

EXEC SQL
    SELECT SALDO
    ...
END-EXEC

é um exemplo clássico de SQL embutido estático.

Conceitualmente:

STATIC SQL

conhecido durante
preparação/deployment
       │
       ▼
processamento
       │
       ▼
DBRM
       │
       ▼
BIND
       │
       ▼
PACKAGE

Mas existe SQL dinâmico.

Podemos ter situações nas quais a instrução é preparada durante a execução usando mecanismos como PREPARE e EXECUTE.

Isso oferece flexibilidade, mas muda aspectos da preparação e execução.

Novamente:

não existe “um é sempre melhor”.

Existe:

qual mecanismo atende melhor ao problema?


19. O crime perfeito: SELECT *

Kojak encontra:

SELECT *
FROM CLIENTE

Olha para o programador.

Olha novamente para a tela.

— Você precisa de todas essas colunas?

— Não.

— Então por que pediu?

Silêncio.

Essa pergunta vale ouro.

Evite transportar dados desnecessários.

Se precisa de:

NOME
SALDO

não peça quarenta colunas simplesmente porque:

SELECT *

é mais rápido de digitar.

Cinco segundos economizados na programação podem gerar trabalho desnecessário repetido milhões de vezes em produção.


20. Outro suspeito: SELECT dentro de LOOP

Agora Kojak encontra:

PERFORM 100000 TIMES

       SELECT ...

END-PERFORM

Acende a luz da sala de interrogatório.

Dependendo do problema, isso pode representar enorme quantidade de chamadas e processamento que talvez pudesse ser resolvida por uma estratégia SQL muito melhor.

O erro conceitual é tratar banco relacional como arquivo sequencial:

LEIA
LEIA
LEIA
LEIA
LEIA

SQL trabalha naturalmente com conjuntos.

Essa mudança de pensamento é enorme para quem vem de COBOL procedural.


21. Não coloque toda a investigação num único SQL monstruoso

Mas existe o extremo oposto.

Alguém aprende que SQL trabalha com conjuntos e produz:

SELECT
 JOIN
  JOIN
   JOIN
    CASE
     CASE
      SUBQUERY
       UNION
        CTE
         FUNCTION
          JOIN
           ...

O SQL parece o mapa genealógico de Game of Thrones.

SQL complexo não é automaticamente ruim.

Às vezes uma operação sofisticada no banco é exatamente a solução correta.

Mas complexidade precisa possuir justificativa.

Legibilidade importa.

Manutenção importa.

Performance importa.

Testabilidade importa.


22. EXPLAIN — reconstruindo a cena do crime

Se queremos investigar desempenho, precisamos saber mais sobre o access path.

É aí que conceitos relacionados ao EXPLAIN tornam-se fundamentais.

O objetivo é investigar como o Db2 pretende ou decidiu acessar os dados, conforme o cenário analisado.

Você começa a procurar pistas:

INDEX?
TABLESPACE SCAN?
JOIN METHOD?
JOIN ORDER?
ESTIMATIVAS?
SORT?

Kojak coloca fotografias na parede.

Agora temos uma investigação de verdade.

O programador deixa de dizer:

“Esse SELECT está lento.”

E começa a perguntar:

“Qual access path está sendo utilizado e por quê?”

Essa diferença separa palpite de diagnóstico.


23. O verdadeiro CPD aparece

Finalmente afastamos a câmera.

O programador pensava que estava trabalhando com:

COBOL + DB2

Mas agora enxerga:

                    z/OS
                      │
       ┌──────────────┼──────────────┐
       │              │              │
      JES2           CICS           Db2
       │              │              │
      JCL            COBOL          SQL
       │              │              │
    datasets           ├──────────────┤
                       │              │
                       MQ          PACKAGE
                       │              │
                      API         OPTIMIZER
                                      │
                                  ACCESS PATH
                                      │
                              ┌───────┴───────┐
                              │               │
                           INDEXES          TABLES

E ainda não terminamos.

Ao redor estão:

RACF
SMF
WLM
TCP/IP
LOGS
RECOVERY
BACKUP
MONITORAMENTO
PARALLEL SYSPLEX

Agora entendemos por que profissionais podem trabalhar décadas com mainframe e continuar aprendendo.


24. Kojak finalmente resolve o caso

Voltamos às 03:17.

O programa estava correto.

O SQL também.

O Db2 estava disponível.

O problema estava relacionado à concorrência.

Outra unidade de trabalho estava mantendo recursos necessários.

A transação esperou.

O limite foi atingido.

O SQL recebeu erro.

O programa não possuía tratamento suficientemente inteligente.

A mensagem apresentada ao operador foi:

ERRO NO BANCO

Ou seja:

o único inocente da investigação talvez fosse justamente “o banco”.

Kojak olha para o programador.

— Então você acusou Db2 sem verificar SQLCODE, reason code, locks, unidade de trabalho e logs?

— Sim.

Kojak coloca o pirulito na boca.

— Who loves ya, baby?


🍭 Easter egg — por que Kojak usa pirulito?

Esse detalhe é perfeito para nossa história.

O pirulito não nasceu simplesmente como um adereço aleatório inventado pelo departamento de marketing. Telly Savalas contou posteriormente que a ideia surgiu numa situação em que uma personagem queria que Kojak parasse de fumar e lhe entregava um pirulito; o detalhe pegou e tornou-se uma das marcas visuais do personagem. (Los Angeles Times)

Na própria série, o pirulito apareceu durante a primeira temporada e acabou associado à tentativa de reduzir o cigarro. (Wikipedia)

Ou seja:

pequena decisão
      │
      ▼
efeito inesperado
      │
      ▼
torna-se característica permanente

Qualquer semelhança com sistemas legados é absolutamente maravilhosa.

Um programador em 1984 cria:

05 WS-FLAG PIC X.

para resolver temporariamente um problema.

Quarenta anos depois:

“Não mexa no WS-FLAG. Ninguém sabe exatamente por quê, mas o fechamento mensal depende dele.”

😂


25. A lição que Kojak deixaria ao programador COBOL

O grande erro de quem começa no mainframe é imaginar que aprender COBOL significa aprender sintaxe:

MOVE
COMPUTE
IF
EVALUATE
PERFORM

Isso é apenas a porta de entrada.

Depois vem:

COBOL
  +
JCL
  +
Db2
  +
CICS
  +
VSAM
  +
MQ
  +
RACF
  +
JES2
  +
WLM
  +
SMF
  +
z/OS

E finalmente você percebe:

o sistema corporativo não é um programa. É um ecossistema de componentes cooperando.

O SELECT SALDO que parece possuir cinco linhas pode envolver host variables, processamento SQL, DBRM, package, optimizer, estatísticas, índices, buffer management, locking, logging, segurança, recuperação e infraestrutura antes de devolver alguns bytes para WS-SALDO.

Essa é uma das coisas mais bonitas do mainframe.

Na superfície:

EXEC SQL
   SELECT SALDO
   INTO :WS-SALDO
...
END-EXEC.

Debaixo:

               50 ANOS
                  DE
             ENGENHARIA
                  │
                  ▼
             WS-SALDO

O programador olha para a variável.

Depois olha para Kojak.

Finalmente compreendeu.

Não basta perguntar:

“O programa compilou?”

É preciso investigar:

Qual SQL executou? Qual SQLCODE retornou? Qual package? Qual access path? As estatísticas estão adequadas? Existe índice apropriado? Houve locking? Timeout? Deadlock? Onde começa e termina a unidade de trabalho? Houve COMMIT? O que os logs mostram?

Porque produção não aceita álibi.

Produção aceita evidência.

Kojak se levanta, pega o sobretudo e caminha para a porta do CPD.

O programador pergunta:

— Tenente, e se amanhã aparecer outro -911?

Kojak sorri.

— Agora você sabe interrogar os suspeitos, baby.

E sai.

Na mesa fica apenas um pirulito, um dump, três relatórios de performance e um post-it:

****************************************
* NÃO CULPE O DB2 ANTES DO EXPLAIN.    *
****************************************

Fim do JOB.

IEF404I KOJAK - ENDED
IEF142I KOJAK STEP01 - COND CODE 0000

E, pela primeira vez naquela madrugada, ninguém precisou dar ROLLBACK no café. ☕🍭

terça-feira, 6 de agosto de 2024

SQLCODE sem Mistérios : O Guia de Sobrevivência do Programador COBOL Padawan diante dos Principais Erros do Db2

 

Bellacosa Mainframe e o sqlcode sem misterios

☕ Um Café no Bellacosa Mainframe

SQLCODE sem Mistérios

O Guia de Sobrevivência do Programador COBOL Padawan diante dos Principais Erros do Db2

Imagine a seguinte cena.

Você acabou de escrever seu primeiro programa COBOL acessando uma tabela Db2. O código compilou. O pré-compilador não reclamou. O BIND terminou aparentemente bem. O JCL foi submetido. O job entrou no JES2, executou alguns segundos e terminou com uma mensagem misteriosa:

SQLCODE = -805

O jovem Padawan olha para o número e pensa:

“Meu programa abendou?”

Talvez sim. Talvez não.

Um SQLCODE negativo não é necessariamente um ABEND do sistema operacional. Ele é uma resposta do Db2 informando que não conseguiu executar determinada instrução SQL. É como se o banco de dados dissesse:

“Recebi sua solicitação, mas existe alguma coisa errada. Aqui está o código que explica o motivo.”

O segredo não é decorar centenas de números. O verdadeiro conhecimento está em aprender a interpretar o contexto, capturar as informações do SQLCA, identificar a instrução que falhou e seguir uma sequência organizada de diagnóstico.

É exatamente isso que faremos neste artigo.

Prepare a caneca, abra o SDSF e venha conhecer o lado Jedi do tratamento de erros SQL em COBOL.


1. Antes do SQLCODE: como COBOL e Db2 conversam?

Um programa COBOL não entende SQL nativamente da mesma maneira que entende comandos como:

MOVE
ADD
PERFORM
READ
WRITE

As instruções SQL aparecem dentro do programa como SQL embutido:

EXEC SQL
    SELECT NOME_CLIENTE
      INTO :WS-NOME-CLIENTE
      FROM CLIENTE
     WHERE COD_CLIENTE = :WS-COD-CLIENTE
END-EXEC.

Durante a preparação do programa, um pré-compilador ou coprocessador Db2 identifica os blocos delimitados por EXEC SQL e END-EXEC, separa o SQL do código COBOL e prepara as estruturas necessárias para a execução. A documentação da IBM estabelece justamente esse formato para aplicações COBOL que emitem comandos SQL. (IBM)

Quando o programa executa uma instrução SQL, o Db2 precisa devolver uma resposta.

Essa resposta inclui, entre outras informações:

  • se a instrução funcionou;

  • se ocorreu um aviso;

  • se nenhum registro foi localizado;

  • se houve erro;

  • qual objeto estava envolvido;

  • quais tokens complementam a mensagem;

  • qual estado SQL representa a situação.

É nesse momento que entra o SQLCA.


2. O que é SQLCA?

SQLCA significa:

SQL Communication Area

Em português:

Área de Comunicação SQL

Ela é uma estrutura de dados usada para transportar informações entre o mecanismo SQL e o programa hospedeiro, como COBOL, PL/I, C ou Assembler.

No COBOL, normalmente incluímos essa estrutura assim:

EXEC SQL
    INCLUDE SQLCA
END-EXEC.

Durante o processo de pré-compilação, essa instrução é substituída pela definição correspondente da estrutura SQLCA. A IBM documenta a composição gerada pelo INCLUDE SQLCA para as diferentes linguagens hospedeiras. (IBM)

Conceitualmente, a origem do SQLCA está ligada à necessidade criada pelo SQL embutido: o banco precisava de uma área padronizada para devolver o resultado de cada operação ao programa que o chamou.

Pense nela como uma pequena central de mensagens.

O COBOL envia:

SELECT este cliente.

O Db2 responde através da SQLCA:

Encontrei.
Não encontrei.
Encontrei, mas houve aviso.
Não consegui porque a tabela não existe.
Não consegui porque o package não foi localizado.
Não consegui porque outro processo está segurando o recurso.

O SQLCODE é apenas o campo mais famoso dessa estrutura.


3. Anatomia básica do SQLCA

Uma representação simplificada da SQLCA em COBOL seria semelhante a esta:

01 SQLCA.
   05 SQLCAID          PIC X(8).
   05 SQLCABC          PIC S9(9) COMP-5.
   05 SQLCODE          PIC S9(9) COMP-5.
   05 SQLERRM.
      49 SQLERRML      PIC S9(4) COMP-5.
      49 SQLERRMC      PIC X(70).
   05 SQLERRP          PIC X(8).
   05 SQLERRD OCCURS 6 TIMES
                       PIC S9(9) COMP-5.
   05 SQLWARN.
      10 SQLWARN0      PIC X.
      10 SQLWARN1      PIC X.
      10 SQLWARN2      PIC X.
      10 SQLWARN3      PIC X.
      10 SQLWARN4      PIC X.
      10 SQLWARN5      PIC X.
      10 SQLWARN6      PIC X.
      10 SQLWARN7      PIC X.
      10 SQLWARN8      PIC X.
      10 SQLWARN9      PIC X.
      10 SQLWARNA      PIC X.
   05 SQLSTATE         PIC X(5).

A definição exata pode variar conforme plataforma, compilador e versão, mas os conceitos permanecem.

SQLCODE

É o código numérico principal retornado pelo Db2.

0       Operação bem-sucedida
+100    Nenhum dado encontrado
positivo diferente de +100
        Operação concluída com aviso
negativo
        Erro

A IBM define que SQLCODE 0 representa sucesso, +100 indica ausência de dados e valores negativos indicam que a execução não foi bem-sucedida. (IBM)

SQLSTATE

É um código de cinco caracteres que classifica a condição de maneira mais padronizada.

Exemplo:

02000

Representa a condição “nenhum dado encontrado”, equivalente ao SQLCODE +100.

SQLCODE é muito usado historicamente em ambientes Db2 e mainframe. SQLSTATE é útil por apresentar uma categorização mais padronizada entre diferentes sistemas gerenciadores de bancos de dados.

SQLERRMC

Contém tokens associados à mensagem.

Se o erro envolver o nome de uma tabela, coluna, package, plano ou autorização, essa área pode trazer justamente a informação que faltava para entender o problema.

SQLERRML

Informa o comprimento válido do conteúdo de SQLERRMC.

Portanto, não é uma boa prática exibir os 70 bytes de SQLERRMC indiscriminadamente. O ideal é considerar a quantidade indicada por SQLERRML.

SQLERRP

Pode identificar o módulo ou componente que detectou a condição. No Db2 for z/OS, os primeiros caracteres normalmente trazem a assinatura DSN. (IBM)

SQLERRD

É um conjunto de campos numéricos com informações complementares.

Dependendo da instrução e do SQLCODE, eles podem indicar:

  • quantidade de linhas afetadas;

  • códigos internos;

  • informações relacionadas ao processamento;

  • razão complementar de determinadas condições.

A interpretação dos campos SQLERRD depende do contexto. Portanto, nunca conclua que um determinado índice possui sempre o mesmo significado em qualquer SQLCODE.

SQLWARN

É um conjunto de indicadores de aviso.

Quando SQLWARN0 contém W, pelo menos uma condição de warning foi identificada. Outros campos mostram categorias específicas de aviso, como truncamento ou situações relacionadas aos dados retornados. A SQLCA utiliza esse conjunto de indicadores para comunicar warnings ao programa. (IBM)


4. A primeira regra Jedi: sempre teste o SQLCODE

Um dos erros mais perigosos não é receber um SQLCODE negativo.

É ignorá-lo.

Observe este código:

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE NUM_CONTA = :WS-NUM-CONTA
END-EXEC.

DISPLAY 'SALDO: ' WS-SALDO.

O que acontecerá se a conta não existir?

O Db2 retornará +100. Entretanto, se o programa não verificar o resultado, WS-SALDO poderá continuar contendo um valor anterior, zeros, espaços ou dados residuais.

O programa poderá apresentar um saldo incorreto como se fosse válido.

O padrão correto é:

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE NUM_CONTA = :WS-NUM-CONTA
END-EXEC.

EVALUATE TRUE
    WHEN SQLCODE = 0
         PERFORM 3000-PROCESSAR-SALDO

    WHEN SQLCODE = +100
         PERFORM 3100-CONTA-NAO-ENCONTRADA

    WHEN OTHER
         PERFORM 9000-TRATAR-ERRO-SQL
END-EVALUATE.

Esse modelo deixa explícitos três caminhos:

sucesso;
ausência de dados;
erro inesperado.

5. SQLCODE 0 — sucesso, mas continue atento

SQLCODE = 0 significa que a instrução foi executada com sucesso.

Exemplo:

EXEC SQL
    UPDATE CONTA
       SET SALDO = SALDO - :WS-VALOR
     WHERE NUM_CONTA = :WS-NUM-CONTA
END-EXEC.

Entretanto, existe uma armadilha.

Um UPDATE pode retornar SQLCODE zero e ainda assim não ter atualizado a quantidade de linhas que sua regra de negócio esperava.

Imagine uma rotina que deveria alterar exatamente uma linha.

Mesmo após SQLCODE zero, pode ser importante verificar a quantidade de linhas afetadas usando as informações apropriadas da SQLCA, de acordo com a instrução e o ambiente.

A pergunta profissional não é apenas:

“Funcionou?”

É também:

“Funcionou exatamente como a regra de negócio esperava?”


6. SQLCODE +100 — nenhum dado encontrado

O +100 é provavelmente o SQLCODE positivo mais conhecido.

Ele significa:

No data found.

Nenhum dado foi encontrado.

Isso pode ocorrer em situações como:

  • SELECT INTO sem linha correspondente;

  • FETCH após o final do cursor;

  • determinadas operações que esperavam encontrar um registro;

  • exclusão ou atualização sem correspondência, conforme a instrução e o contexto.

A IBM associa o SQLCODE +100 e o SQLSTATE 02000 à condição NOT FOUND. (IBM)

Exemplo com SELECT

EXEC SQL
    SELECT NOME
      INTO :WS-NOME
      FROM CLIENTE
     WHERE COD_CLIENTE = :WS-COD-CLIENTE
END-EXEC.

IF SQLCODE = +100
    DISPLAY 'CLIENTE NAO ENCONTRADO'
END-IF.

Exemplo com cursor

PERFORM UNTIL WS-FIM-CURSOR = 'S'

    EXEC SQL
        FETCH C1
         INTO :WS-CODIGO,
              :WS-NOME
    END-EXEC

    EVALUATE TRUE
        WHEN SQLCODE = 0
             PERFORM 4000-PROCESSAR-CLIENTE

        WHEN SQLCODE = +100
             MOVE 'S' TO WS-FIM-CURSOR

        WHEN OTHER
             PERFORM 9000-TRATAR-ERRO-SQL
    END-EVALUATE

END-PERFORM.

Possíveis soluções

  1. Verifique se os valores das host variables estão corretos.

  2. Confirme se a linha realmente existe na tabela.

  3. Verifique espaços, zeros à esquerda e formatos de data.

  4. Confirme se o predicado WHERE não está restritivo demais.

  5. Em cursores, trate +100 como fim normal da leitura.

  6. Inicialize as variáveis de saída antes do SELECT.

Dica Bellacosa

Não trate todo +100 como erro técnico.

Em muitos programas, “cliente não encontrado” é uma condição normal de negócio. Em um cursor, +100 é praticamente o equivalente SQL ao fim de arquivo.


7. SQLCODE -204 — objeto não definido

O -204 informa que o objeto referenciado não está definido no subsistema ou contexto em que a instrução está sendo executada. A documentação da IBM cita essa condição para diferentes tipos de objetos Db2. (IBM)

Exemplo:

SELECT *
  FROM CLIENTES

Mas a tabela correta é:

SISTEMA1.CLIENTE

Causas comuns

  • nome da tabela digitado incorretamente;

  • creator ou schema ausente;

  • tabela existente em outro ambiente;

  • synonym, alias ou view inexistente;

  • programa executando em outro subsistema Db2;

  • objeto ainda não criado;

  • qualificador definido incorretamente no BIND;

  • diferença entre desenvolvimento, homologação e produção.

Passo a passo

  1. Capture o conteúdo de SQLERRMC.

  2. Identifique o nome exato do objeto mencionado.

  3. Confirme o subsistema Db2 em que o programa executou.

  4. Pesquise o catálogo Db2.

  5. Verifique o schema ou creator.

  6. Compare o DDL entre os ambientes.

  7. Verifique os parâmetros de qualificação usados no BIND.

  8. Corrija o nome ou solicite a criação do objeto.

Exemplo de correção

Antes:

EXEC SQL
    SELECT NOME
      INTO :WS-NOME
      FROM CLIENTE
     WHERE CODIGO = :WS-CODIGO
END-EXEC.

Depois:

EXEC SQL
    SELECT NOME
      INTO :WS-NOME
      FROM CADASTRO.CLIENTE
     WHERE CODIGO = :WS-CODIGO
END-EXEC.

8. SQLCODE -206 — coluna não encontrada ou inválida

O -206 geralmente indica que o nome de uma coluna não é válido no contexto da instrução.

Exemplo:

SELECT NOME_COMPLETO
  FROM CLIENTE

Mas a coluna real se chama:

NOME_CLIENTE

Causas comuns

  • erro de digitação;

  • coluna removida ou renomeada;

  • referência incorreta a alias de tabela;

  • SQL dinâmico montado de maneira errada;

  • DCLGEN desatualizada;

  • programa compilado com uma versão antiga do layout;

  • promoção incompleta entre ambientes.

Diagnóstico

  1. Identifique a coluna em SQLERRMC.

  2. Consulte a definição atual da tabela.

  3. Compare o SQL com a DCLGEN.

  4. Confirme se o alias da tabela foi usado corretamente.

  5. Verifique se a coluna pertence à tabela esperada.

  6. Atualize e regenere as estruturas, se necessário.

Armadilha clássica

SELECT C.NOME
  FROM CLIENTE X

A tabela recebeu o alias X, mas a coluna foi qualificada com C.

A correção seria:

SELECT X.NOME
  FROM CLIENTE X

9. SQLCODE -305 — valor NULL sem indicador

O -305 é um dos primeiros grandes encontros do programador COBOL com a diferença entre o mundo COBOL e o mundo relacional.

No Db2, uma coluna pode possuir valor NULL.

No COBOL tradicional, uma variável hospedeira comum não possui, sozinha, um terceiro estado que signifique “valor desconhecido ou ausente”.

Por isso usamos uma variável indicadora.

Exemplo incorreto:

EXEC SQL
    SELECT COMPLEMENTO
      INTO :WS-COMPLEMENTO
      FROM ENDERECO
     WHERE COD_CLIENTE = :WS-COD-CLIENTE
END-EXEC.

Se COMPLEMENTO for NULL, o programa poderá receber -305.

Correção

01 WS-COMPLEMENTO       PIC X(30).
01 IND-COMPLEMENTO      PIC S9(4) COMP-5.

EXEC SQL
    SELECT COMPLEMENTO
      INTO :WS-COMPLEMENTO
          :IND-COMPLEMENTO
      FROM ENDERECO
     WHERE COD_CLIENTE = :WS-COD-CLIENTE
END-EXEC.

Depois:

IF IND-COMPLEMENTO < 0
    MOVE 'NAO INFORMADO' TO WS-COMPLEMENTO
END-IF.

Regra prática

Indicador negativo:

o valor recebido é NULL.

Indicador zero:

o valor não é NULL.

Certas condições positivas podem representar informações adicionais, como truncamento, dependendo da operação.

Passo a passo

  1. Descubra qual coluna permite NULL.

  2. Adicione uma variável indicadora compatível.

  3. Associe o indicador à host variable.

  4. Verifique o indicador após a instrução.

  5. Defina a regra de negócio para valores nulos.

  6. Não confunda NULL com espaços ou zeros.


10. SQLCODE -302 — valor incompatível ou grande demais

O -302 costuma indicar que uma variável de entrada possui um valor incompatível com o tipo ou tamanho esperado.

Exemplo:

01 WS-CODIGO PIC X(20).

A coluna Db2 espera um número pequeno, mas o programa envia:

ABC123

Também pode haver problemas de comprimento, precisão, escala ou representação.

Causas comuns

  • conteúdo alfanumérico enviado para coluna numérica;

  • número maior do que a coluna suporta;

  • escala decimal incompatível;

  • data em formato inválido;

  • host variable com definição incorreta;

  • estrutura COBOL divergente do DCLGEN;

  • indicador ou comprimento incorreto.

Passo a passo

  1. Exiba o valor da host variable antes do SQL.

  2. Verifique o tipo da coluna no catálogo.

  3. Compare PIC, USAGE, comprimento, precisão e escala.

  4. Valide dados recebidos de arquivo, tela ou API.

  5. Verifique sinais e casas decimais.

  6. Utilize DCLGEN atualizada.

  7. Não corrija apenas aumentando o campo sem entender a origem do valor.

Exemplo

Coluna:

VALOR DECIMAL(9,2)

Host variable recomendada:

01 WS-VALOR PIC S9(7)V99 COMP-3.

Um erro de definição poderia fazer o programa enviar uma representação incompatível.


11. SQLCODE -303 — tipos incompatíveis na atribuição

O -303 aparece quando o Db2 não consegue atribuir um valor à variável hospedeira devido à incompatibilidade de tipos.

Exemplo conceitual:

SELECT DATA_NASCIMENTO
  INTO :WS-VALOR-NUMERICO

Se WS-VALOR-NUMERICO não possuir definição compatível com uma data, haverá problema.

Solução

  • compare o tipo da coluna com a PIC da host variable;

  • use DCLGEN;

  • faça conversões explícitas quando justificadas;

  • evite depender de conversões implícitas;

  • verifique CCSID e codificação quando o erro envolver caracteres;

  • confira precisão e escala em campos decimais.


12. SQLCODE -407 — tentativa de gravar NULL em coluna NOT NULL

O -407 representa a tentativa de atribuir NULL a uma coluna que não aceita valores nulos.

Isso pode ocorrer em:

  • INSERT;

  • UPDATE;

  • processamento de indicadores;

  • triggers;

  • valores omitidos sem default apropriado.

Exemplo

INSERT INTO CLIENTE
       (CODIGO, NOME)
VALUES (:HV-CODIGO, :HV-NOME)

Se o indicador associado a HV-NOME estiver negativo, o programa estará tentando inserir NULL.

Caso NOME seja NOT NULL, a operação falhará.

Passo a passo

  1. Identifique a coluna envolvida.

  2. Verifique os indicadores.

  3. Consulte a definição NULL/NOT NULL.

  4. Confirme se existe valor default.

  5. Valide os campos obrigatórios antes do SQL.

  6. Não substitua NULL por espaços sem autorização da regra de negócio.


13. SQLCODE -803 — chave duplicada

O -803 é o guardião da unicidade.

Ele geralmente ocorre quando um INSERT ou UPDATE tenta gerar um valor que viola um índice único ou uma restrição de unicidade.

Exemplo:

INSERT INTO CLIENTE
       (COD_CLIENTE, NOME)
VALUES (100, 'ANA')

Mas já existe um cliente com código 100.

Causas comuns

  • chave primária já existente;

  • índice único violado;

  • contador ou sequência mal controlada;

  • reprocessamento do mesmo arquivo;

  • mensagem MQ processada duas vezes;

  • reinício de job sem checkpoint;

  • concorrência entre processos;

  • lógica “consultar e depois inserir” sujeita a corrida.

Passo a passo

  1. Identifique a constraint ou índice envolvido.

  2. Verifique quais colunas formam a chave única.

  3. Consulte o registro existente.

  4. Descubra se é duplicidade real ou reprocessamento.

  5. Verifique a origem da chave.

  6. Avalie o uso de sequence ou identity.

  7. Torne o processamento idempotente quando necessário.

  8. Não resolva apagando o registro anterior sem análise.

Dica de produção

Em sistemas distribuídos, o -803 pode ser sintoma de uma mensagem repetida, não de um erro humano.

A pergunta correta pode ser:

“Por que esta transação chegou duas vezes?”


14. SQLCODE -805 — package não encontrado

O -805 é um clássico do Db2 for z/OS.

Ele normalmente informa que o Db2 não encontrou o package necessário para executar a instrução SQL.

Seu programa foi compilado, linkeditado e executado, mas o componente Db2 correspondente não foi localizado na collection esperada.

Causas comuns

  • DBRM não foi bindado;

  • BIND PACKAGE não foi executado;

  • collection incorreta;

  • versão incorreta;

  • package removido;

  • plano não possui PKLIST adequado;

  • programa executando em subsistema diferente;

  • promoção incompleta;

  • load module novo com package antigo;

  • package novo com load module antigo.

Passo a passo de diagnóstico

  1. Capture todo o conteúdo de SQLERRMC.

  2. Identifique location, collection, package e consistência.

  3. Confirme qual load module foi executado.

  4. Verifique a STEPLIB ou JOBLIB.

  5. Confirme o subsistema Db2.

  6. Consulte o catálogo para verificar se o package existe.

  7. Confira collection e versão.

  8. Verifique o PKLIST do plano.

  9. Execute ou solicite o BIND correto.

  10. Confirme se programa e package pertencem à mesma construção.

Analogia Bellacosa

O load module é o guerreiro.

O package é o pergaminho com a estratégia SQL.

O plano ou contexto de execução é a autorização para usar determinados pergaminhos.

No -805, o guerreiro chegou ao campo de batalha, mas o pergaminho correto não estava na biblioteca.


15. SQLCODE -818 — incompatibilidade de timestamp

O -818 normalmente indica que o módulo executável e o DBRM/package associado não pertencem à mesma preparação.

Em termos simples:

o código COBOL e o código SQL ficaram fora de sincronia.

Cenário clássico

  1. Programa é pré-compilado.

  2. Um novo DBRM é produzido.

  3. O programa é compilado e linkeditado.

  4. O BIND usa um DBRM antigo.

Ou:

  1. O package foi atualizado.

  2. O load module antigo continua na load library.

Solução passo a passo

  1. Identifique o load module carregado.

  2. Confirme a data e versão do módulo.

  3. Identifique o DBRM usado no último BIND.

  4. Refaça toda a cadeia de construção.

  5. Pré-compile novamente.

  6. Compile novamente.

  7. Faça o link-edit novamente.

  8. Execute o BIND novamente.

  9. Promova load module e package como uma unidade.

  10. Verifique se a execução está lendo a biblioteca correta.

Dica DevOps

Nunca trate o package e o executável como artefatos independentes.

Eles são partes da mesma entrega.


16. SQLCODE -811 — SELECT retornou mais de uma linha

Um SELECT INTO espera, normalmente, uma única linha.

Exemplo:

EXEC SQL
    SELECT NOME
      INTO :WS-NOME
      FROM CLIENTE
     WHERE CIDADE = :WS-CIDADE
END-EXEC.

Se existirem cem clientes na cidade, o Db2 não poderá decidir qual nome devolver.

Resultado:

SQLCODE -811

Causas

  • predicado incompleto;

  • premissa errada de unicidade;

  • dados duplicados;

  • constraint ausente;

  • chave incorreta;

  • regra de negócio mudou;

  • SELECT deveria utilizar cursor.

Soluções

Quando deveria existir apenas uma linha

  • corrija o WHERE;

  • consulte pela chave correta;

  • elimine duplicidades de forma controlada;

  • implemente constraint única quando fizer sentido.

Quando várias linhas são válidas

Use cursor:

EXEC SQL
    DECLARE C1 CURSOR FOR
        SELECT NOME
          FROM CLIENTE
         WHERE CIDADE = :WS-CIDADE
END-EXEC.

Cuidado com a falsa solução

Adicionar algo equivalente a “pegue apenas a primeira linha” pode esconder um problema de dados.

Antes de limitar o resultado, pergunte:

“Qual linha é realmente a correta?”


17. SQLCODE -904 — recurso indisponível

O -904 indica que a instrução não foi executada porque um recurso necessário estava indisponível. A mensagem traz informações como reason code, tipo do recurso e nome do recurso. (IBM)

Possíveis causas

  • tablespace parado;

  • objeto em estado restritivo;

  • partição indisponível;

  • utilitário em execução;

  • recurso não iniciado;

  • problema de comunicação;

  • recurso auxiliar indisponível;

  • condição de recuperação pendente.

Passo a passo

  1. Capture o reason code.

  2. Capture o resource type.

  3. Capture o resource name.

  4. Consulte a documentação do reason code.

  5. Verifique mensagens Db2 no log.

  6. Consulte o estado do objeto.

  7. Verifique utilitários ativos.

  8. Acione o DBA ou suporte de produção com os dados completos.

  9. Não tente repetir indefinidamente sem entender a indisponibilidade.

Dica importante

-904 sem reason code é apenas metade do diagnóstico.

Dizer ao DBA:

“Deu menos novecentos e quatro”

é pouco útil.

Dizer:

“SQLCODE -904, reason 00C9..., resource type ..., resource name ...”

transforma um pedido genérico em uma investigação objetiva.


18. SQLCODE -911 e -913 — deadlock ou timeout

Esses códigos aparecem em situações de contenção, timeout ou deadlock.

Deadlock

Dois processos ficam esperando recursos mantidos um pelo outro.

Exemplo:

Programa A atualiza CLIENTE e espera CONTA.
Programa B atualiza CONTA e espera CLIENTE.

Nenhum consegue continuar.

O Db2 escolhe uma das unidades de trabalho como vítima para liberar o impasse.

Timeout

Um processo aguarda um recurso por mais tempo do que o limite permitido.

Diferença prática

A interpretação exata deve considerar:

  • SQLCODE;

  • reason code;

  • mensagens;

  • rollback executado;

  • ambiente e parâmetros;

  • informações de trace.

Em muitos cenários, -911 aparece quando a unidade de trabalho sofre rollback, enquanto -913 pode indicar uma condição semelhante sem o mesmo comportamento automático de rollback. A confirmação deve ser feita pelos dados complementares, especialmente reason code e SQLERRD. (Comunidade IBM)

Possíveis soluções

  1. Reduza o tempo entre commits.

  2. Não mantenha cursor ou unidade de trabalho aberta desnecessariamente.

  3. Acesse tabelas na mesma ordem em todos os programas.

  4. Atualize somente as linhas necessárias.

  5. Garanta bons índices.

  6. Evite varreduras extensas durante updates.

  7. Analise isolamento e concorrência.

  8. Implemente retry controlado quando permitido.

  9. Não faça retry infinito.

  10. Registre tentativa, horário e chave processada.

Exemplo de retry controlado

MOVE 0 TO WS-TENTATIVAS.

PERFORM UNTIL WS-SUCESSO = 'S'
           OR WS-TENTATIVAS >= 3

    ADD 1 TO WS-TENTATIVAS

    PERFORM 5000-EXECUTAR-TRANSACAO

    EVALUATE SQLCODE
        WHEN 0
             MOVE 'S' TO WS-SUCESSO

        WHEN -911
             PERFORM 5100-PREPARAR-NOVA-TENTATIVA

        WHEN -913
             PERFORM 5100-PREPARAR-NOVA-TENTATIVA

        WHEN OTHER
             PERFORM 9000-TRATAR-ERRO-SQL
             MOVE 'S' TO WS-ENCERRAR
    END-EVALUATE

END-PERFORM.

O retry precisa respeitar a arquitetura da aplicação. Em alguns casos, repetir a operação automaticamente pode duplicar efeitos externos.


19. SQLCODE -922 — falha de autorização

O -922 normalmente está relacionado à autorização, conexão ou acesso a recursos do Db2.

Possíveis causas

  • usuário sem privilégio;

  • plano sem autorização;

  • package sem autorização de execução;

  • falha na conexão;

  • contexto de segurança incorreto;

  • autorização RACF ou Db2 ausente;

  • ambiente executando com outro ID;

  • mudança de owner ou qualifier.

Passo a passo

  1. Identifique o authorization ID em uso.

  2. Capture os tokens da SQLCA.

  3. Verifique o privilégio exigido.

  4. Confirme quem é o owner do package.

  5. Verifique autorização de EXECUTE.

  6. Confira plano, collection e contexto de execução.

  7. Analise mensagens SAF/RACF quando aplicável.

  8. Solicite o GRANT correto.

  9. Nunca peça privilégios excessivos apenas para “fazer funcionar”.


20. SQLCODE -501, -502 e -514 — problemas com cursor

-501

Tentativa de executar FETCH ou CLOSE em cursor que não está aberto.

-502

Tentativa de abrir um cursor que já está aberto.

-514

O cursor não está em estado adequado para a operação, frequentemente por não estar preparado corretamente em cenários de SQL dinâmico.

Checklist de cursor

A sequência esperada é:

DECLARE
OPEN
FETCH
FETCH
FETCH
...
+100
CLOSE

No COBOL:

EXEC SQL
    OPEN C1
END-EXEC.

IF SQLCODE NOT = 0
    PERFORM 9000-TRATAR-ERRO-SQL
END-IF.

PERFORM UNTIL WS-FIM = 'S'

    EXEC SQL
        FETCH C1
         INTO :WS-CODIGO,
              :WS-NOME
    END-EXEC

    EVALUATE SQLCODE
        WHEN 0
             PERFORM 4000-PROCESSAR
        WHEN +100
             MOVE 'S' TO WS-FIM
        WHEN OTHER
             PERFORM 9000-TRATAR-ERRO-SQL
             MOVE 'S' TO WS-FIM
    END-EVALUATE

END-PERFORM.

EXEC SQL
    CLOSE C1
END-EXEC.

Dica

Use flags explícitas:

01 WS-CURSOR-ABERTO PIC X VALUE 'N'.
01 WS-FIM-CURSOR    PIC X VALUE 'N'.

Elas ajudam a impedir OPEN duplicado ou FETCH após fechamento.


21. WHENEVER: útil, mas não mágico

O Db2 permite instruções como:

EXEC SQL
    WHENEVER SQLERROR
    GO TO 9000-ERRO-SQL
END-EXEC.

Também existem:

EXEC SQL
    WHENEVER NOT FOUND
    GO TO 8000-NAO-ENCONTRADO
END-EXEC.

EXEC SQL
    WHENEVER SQLWARNING
    GO TO 8500-WARNING-SQL
END-EXEC.

A IBM documenta que:

  • NOT FOUND corresponde ao +100;

  • SQLERROR corresponde a SQLCODE negativo;

  • SQLWARNING cobre warnings e códigos positivos diferentes de +100. (IBM)

Entretanto, existe uma característica importante:

WHENEVER é uma diretiva tratada durante a preparação do SQL embutido. Seu efeito depende da posição em que aparece no fonte.

Ela não funciona exatamente como uma configuração dinâmica COBOL tradicional.

Risco

Um programador pode colocar:

EXEC SQL
    WHENEVER SQLERROR GO TO 9000-ERRO
END-EXEC.

e depois esquecer que todas as instruções SQL seguintes estarão sujeitas a esse desvio, até que outra diretiva altere o comportamento.

Alternativa explícita

Muitas equipes preferem:

EXEC SQL
    WHENEVER SQLERROR CONTINUE
END-EXEC.

E verificam o SQLCODE após cada comando:

EXEC SQL
    DELETE FROM TEMPORARIA
     WHERE CHAVE = :WS-CHAVE
END-EXEC.

PERFORM 9100-VERIFICAR-SQL.

Isso pode tornar o fluxo mais previsível.


22. Uma rotina COBOL centralizada de tratamento

Uma boa aplicação não deveria espalhar dezenas de DISPLAY SQLCODE improvisados.

Crie uma rotina padronizada:

9000-TRATAR-ERRO-SQL.

    DISPLAY '**************************************'
    DISPLAY '* ERRO DB2                           *'
    DISPLAY '**************************************'
    DISPLAY 'PROGRAMA : ' WS-NOME-PROGRAMA
    DISPLAY 'PARAGRAFO: ' WS-PARAGRAFO-ATUAL
    DISPLAY 'OPERACAO : ' WS-OPERACAO-SQL
    DISPLAY 'SQLCODE  : ' SQLCODE
    DISPLAY 'SQLSTATE : ' SQLSTATE
    DISPLAY 'SQLERRP  : ' SQLERRP
    DISPLAY 'SQLERRML : ' SQLERRML
    DISPLAY 'SQLERRMC : ' SQLERRMC
    DISPLAY 'SQLERRD1 : ' SQLERRD (1)
    DISPLAY 'SQLERRD2 : ' SQLERRD (2)
    DISPLAY 'SQLERRD3 : ' SQLERRD (3)
    DISPLAY 'SQLERRD4 : ' SQLERRD (4)
    DISPLAY 'SQLERRD5 : ' SQLERRD (5)
    DISPLAY 'SQLERRD6 : ' SQLERRD (6)
    DISPLAY '**************************************'

    MOVE 12 TO RETURN-CODE.

Em produção, avalie cuidados com dados sensíveis. Não exiba:

  • senhas;

  • tokens;

  • informações pessoais desnecessárias;

  • números completos de documentos;

  • dados financeiros sigilosos;

  • comandos SQL contendo informações protegidas.

A observabilidade deve ajudar o diagnóstico sem criar uma nova vulnerabilidade.


23. O passo a passo universal de diagnóstico

Quando aparecer um SQLCODE inesperado, siga esta sequência.

Passo 1 — identifique a instrução

Não procure apenas pelo número.

Descubra:

qual programa;
qual parágrafo;
qual instrução SQL;
qual tabela;
qual chave;
qual operação.

Passo 2 — registre a SQLCA

Capture:

SQLCODE;
SQLSTATE;
SQLERRMC;
SQLERRML;
SQLERRP;
SQLERRD;
SQLWARN.

Passo 3 — descubra a categoria

Pergunte:

É sucesso?
É +100?
É warning?
É erro de dados?
É erro de objeto?
É erro de package?
É erro de autorização?
É indisponibilidade?
É concorrência?

Passo 4 — leia os tokens

Muitos SQLCODEs só ficam claros quando analisamos SQLERRMC, reason code, nome do recurso ou nome do objeto.

Passo 5 — reproduza com os mesmos dados

Tente identificar:

  • chave;

  • conteúdo das host variables;

  • ambiente;

  • versão do programa;

  • package;

  • plano;

  • horário;

  • unidade de trabalho.

Passo 6 — compare estruturas

Verifique:

  • DCLGEN;

  • catálogo;

  • copybooks;

  • tipos;

  • comprimentos;

  • indicadores;

  • nullabilidade;

  • índices;

  • constraints.

Passo 7 — corrija a causa, não apenas o sintoma

Exemplo:

Sintoma: -803.
Correção ruim: ignorar toda duplicidade.
Correção real: descobrir por que a transação foi processada novamente.

Passo 8 — crie proteção contra recorrência

Depois de corrigir:

  • adicione validação;

  • melhore o log;

  • crie teste;

  • atualize documentação;

  • ajuste pipeline;

  • implemente monitoramento;

  • reveja commit e rollback.


24. COMMIT e ROLLBACK: a responsabilidade do Padawan

Uma transação Db2 não é apenas uma sequência de comandos.

Ela é uma unidade lógica de trabalho.

Exemplo:

Debitar conta A.
Creditar conta B.
Registrar movimentação.

Essas três ações precisam ser tratadas como um conjunto.

Se a primeira funcionar e a segunda falhar, você não pode simplesmente continuar.

EXEC SQL
    COMMIT
END-EXEC.

confirma a unidade de trabalho.

EXEC SQL
    ROLLBACK
END-EXEC.

desfaz alterações ainda não confirmadas, dentro das regras e do contexto da aplicação.

Cuidado

Não espalhe commits aleatórios apenas para reduzir locks.

Um commit mal posicionado pode quebrar a atomicidade da transação.

O ponto de commit deve refletir a regra de negócio, não apenas uma tentativa de silenciar problemas de concorrência.


25. Dicas de veterano para o COBOL Padawan

Use DCLGEN

A DCLGEN ajuda a alinhar as colunas Db2 com as variáveis COBOL.

Mas lembre-se:

DCLGEN não é um artefato eterno.

Se a tabela mudar, a declaração precisa ser revisada e regenerada.

Inicialize variáveis

Antes de um SELECT INTO, inicialize as variáveis de saída quando isso fizer sentido.

Isso evita o uso acidental de conteúdo anterior após um +100.

Registre o ponto da falha

Antes da instrução:

MOVE 'SELECT-CLIENTE'
  TO WS-OPERACAO-SQL.

Assim a rotina central sabe exatamente qual comando falhou.

Não use apenas DISPLAY

Em aplicações maduras, prefira uma estratégia padronizada de logging, mensagens de aplicação, códigos de retorno e integração com observabilidade.

Diferencie erro técnico de erro de negócio

+100 procurando cliente opcional:
condição de negócio.

-805:
erro técnico de implantação.

-803 ao reprocessar mensagem:
pode representar condição funcional de idempotência.

-911:
condição técnica de concorrência que talvez permita retry.

Conheça o ambiente

Em Db2 for z/OS, o diagnóstico frequentemente envolve muito mais do que o fonte:

  • subsistema Db2;

  • catálogo;

  • package;

  • collection;

  • plan;

  • DBRM;

  • BIND;

  • load library;

  • RACF;

  • JES2;

  • SDSF;

  • logs;

  • utilitários;

  • locks.


26. Curiosidade: SQLCODE não é ABEND

Um SQLCODE negativo indica que uma instrução SQL falhou.

Um ABEND indica encerramento anormal de uma task, job step ou programa.

Os dois podem aparecer juntos, mas não são a mesma coisa.

Um programa bem escrito pode receber -803, tratar a duplicidade e continuar.

Outro programa pode receber +100, ignorar a condição e mais tarde causar um S0C7 porque tentou usar dados inválidos.

Portanto:

SQLCODE negativo não significa automaticamente ABEND.
SQLCODE positivo não significa automaticamente que tudo está correto.

O resultado depende da maneira como o programa reage.


27. Easter egg do Bellacosa Mainframe

Nos filmes, o jovem Jedi pergunta:

“Mestre, como saberei qual caminho seguir?”

O mestre responde:

“Observe a Força.”

No Db2, a resposta seria:

“Observe a SQLCA.”

O SQLCODE mostra a direção geral.

O SQLSTATE mostra a categoria.

O SQLERRMC revela os personagens envolvidos.

O reason code explica a motivação do vilão.

O SQLERRD guarda pistas escondidas.

O log do Db2 conta o que aconteceu fora da câmera.

E o programa COBOL decide se deve:

continuar;
encerrar;
repetir;
fazer rollback;
informar o usuário;
acionar o suporte.

O verdadeiro Sith não é o SQLCODE negativo.

O verdadeiro Sith é o programa que recebe uma mensagem de erro, ignora a SQLCA e continua processando dados como se nada tivesse acontecido.


28. Tabela de bolso do Padawan

SQLCODE   SIGNIFICADO PRINCIPAL
-------   ----------------------------------------------
0         Execução bem-sucedida
+100      Nenhum dado encontrado / fim do cursor
-204      Objeto não definido
-206      Coluna inválida ou não encontrada
-302      Valor de entrada incompatível ou excessivo
-303      Tipos incompatíveis
-305      NULL recebido sem variável indicadora
-407      NULL enviado para coluna NOT NULL
-501      Cursor não aberto
-502      Cursor já aberto
-514      Cursor em estado inadequado
-803      Violação de chave ou índice único
-805      Package não encontrado
-811      SELECT INTO retornou mais de uma linha
-818      Incompatibilidade entre módulo e DBRM/package
-904      Recurso indisponível
-911      Timeout/deadlock com impacto na unidade de trabalho
-913      Timeout/deadlock; analisar rollback e reason code
-922      Falha de autorização ou conexão

Essa tabela é um mapa inicial, não substitui a documentação completa. O catálogo de códigos Db2 fornece explicações, ações do sistema e respostas recomendadas para cada condição. (IBM)


Conclusão: o erro é uma mensagem, não uma sentença

Aprender Db2 com COBOL não significa decorar uma enciclopédia de SQLCODEs.

Significa construir um método.

Quando uma instrução falhar:

  1. pare;

  2. identifique o SQL;

  3. capture a SQLCA;

  4. leia o SQLCODE;

  5. consulte o SQLSTATE;

  6. analise os tokens;

  7. identifique objetos e reason codes;

  8. verifique host variables;

  9. confirme package, plano e ambiente;

  10. corrija a causa;

  11. proteja o sistema contra recorrência.

Com o tempo, os números deixam de parecer mensagens alienígenas.

O +100 passa a significar fim normal de cursor.

O -305 lembra imediatamente uma variável indicadora esquecida.

O -803 aponta para unicidade ou reprocessamento.

O -805 faz você olhar para package, collection e BIND.

O -818 lembra que load module e DBRM precisam caminhar juntos.

O -911 acende o alerta de concorrência, commit e retry.

O -904 exige reason code, resource type e resource name.

Nesse momento, o Padawan deixa de perguntar:

“Por que o Db2 quebrou?”

E começa a perguntar:

“Qual condição o Db2 está comunicando, quais evidências ele forneceu e qual é a resposta correta da aplicação?”

Essa mudança de postura é o nascimento de um verdadeiro programador de sistemas corporativos.

Porque no Bellacosa Mainframe, cada SQLCODE é uma pista, cada SQLCA é um mapa e cada erro corretamente tratado é mais uma transação protegida no coração do IBM Z.

 


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...