Translate

terça-feira, 22 de novembro de 2022

BIND PACKAGE e BIND PLAN sem Mistérios O guia do programador COBOL Padawan para transformar um DBRM em SQL executável no Db2 for z/OS

 

Bellacosa Mainframe apresenta bind package e bin plan sem misterios

☕ Um Café no Bellacosa Mainframe

BIND PACKAGE e BIND PLAN sem Mistérios

O guia do programador COBOL Padawan para transformar um DBRM em SQL executável no Db2 for z/OS

Imagine a seguinte cena.

Você passou horas escrevendo um programa COBOL. Revisou a WORKING-STORAGE, declarou corretamente as host variables, incluiu a SQLCA, fechou todos os END-EXEC, compilou o fonte e recebeu um belo retorno RC=0000.

Orgulhoso, você executa o programa.

De repente, o Db2 responde:

SQLCODE = -805

Ou talvez:

SQLCODE = -818

Você olha para o load module, olha para o JCL e pensa:

“Mas o programa compilou! Por que o Db2 diz que não consegue executá-lo?”

É nesse momento que o programador COBOL Padawan descobre uma das grandes verdades do universo mainframe:

Um programa COBOL com SQL não vive apenas dentro do load module.

Ele possui duas metades.

A primeira metade é o código executável:

Fonte COBOL
   ↓
Compilação
   ↓
Objeto
   ↓
Link-edit
   ↓
Load module

A segunda metade é o SQL preparado para o Db2:

SQL embutido
   ↓
DBRM
   ↓
BIND PACKAGE
   ↓
PACKAGE
   ↓
PLAN

Essas duas metades precisam permanecer sincronizadas. Quando isso não acontece, surgem os lendários -805, -818, packages não encontrados, plans inconsistentes e deploys que pareciam perfeitos até o momento em que chegaram à produção.

Neste artigo, vamos desmontar cuidadosamente o JCL apresentado, explicar cada instrução, compreender a relação entre DBRM, package e plan, analisar os erros mais frequentes e construir uma versão mais segura, legível e moderna.

Prepare o café. O ritual do BIND vai começar.


Bellacosa Mainframe e o bind no db2

1. O que é o BIND no Db2?

O BIND é o processo por meio do qual o Db2 recebe as informações SQL extraídas de um programa e as transforma em uma estrutura executável chamada package.

Quando você escreve:

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

o compilador COBOL não sabe interpretar diretamente:

EXEC SQL

Por isso, antes da compilação propriamente dita, o programa passa por um precompiler Db2.

O precompiler separa o programa em duas trilhas.

Trilha COBOL

Ele produz um fonte COBOL modificado, no qual as instruções SQL são substituídas por chamadas apropriadas ao runtime Db2.

Trilha Db2

Ele produz um arquivo chamado:

DBRM

DBRM significa:

Database Request Module

O DBRM contém a representação das instruções SQL estáticas encontradas no programa.

Depois, o comando BIND PACKAGE lê esse DBRM e cria o package.

Em termos simples:

DBRM + opções de BIND + catálogo Db2 = PACKAGE

Durante o BIND, o Db2 pode:

  • verificar os objetos referenciados;

  • conferir autorizações;

  • resolver tabelas, views e aliases;

  • avaliar índices disponíveis;

  • selecionar caminhos de acesso;

  • registrar dependências;

  • definir isolamento;

  • definir encoding;

  • armazenar informações no catálogo;

  • criar o package que será usado durante a execução.

Portanto, o BIND não é uma simples cópia.

Ele é uma etapa de preparação, validação, autorização e otimização.


2. O JCL analisado

O trecho apresentado segue esta estrutura:

//BINDPK03 EXEC PGM=IKJEFT01,COND=(4,LT,COB),
//             DYNAMNBR=20
//DBRMLIB  DD DSN=&&DBRMDB2(COBDB501),DISP=(OLD,DELETE)
//SYSUDUMP DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSTSIN  DD *

 DSN SYSTEM(DB9G)

 BIND PACKAGE(HERPACK) OWNER(INEFE00) MEMBER(COBDB501) -
 ACTION(REP) VALIDATE(BIND) EXPLAIN(NO) DEGREE(1) ISO(UR) -
 ENABLE(*) ENCODING(EBCDIC)

 BIND PLAN(HERP0001) -
 PKLIST(HERPACK.*,HERPACK.COBDB501) -
 ACTION(REP) ISO(UR) ENCODING(EBCDIC)

/*

Esse passo possui duas grandes responsabilidades:

  1. Criar ou substituir o package HERPACK.COBDB501.

  2. Criar ou substituir o plan HERP0001.

Vamos analisar cada parte.


3. O step BINDPK03

//BINDPK03 EXEC PGM=IKJEFT01,COND=(4,LT,COB),
//             DYNAMNBR=20

O nome do step é:

BINDPK03

O nome não possui significado obrigatório para o sistema. Ele é uma convenção criada pela equipe.

Pode significar:

BIND = etapa de bind
PK   = package
03   = terceiro passo do processo

Uma boa nomenclatura ajuda muito durante a análise do spool.

Compare:

//STEP7 EXEC ...

com:

//BINDPKG EXEC ...

Quando há uma falha às duas da manhã, o segundo nome é muito mais amigável.


4. Por que executar IKJEFT01?

PGM=IKJEFT01

O IKJEFT01 permite executar comandos TSO em batch.

Normalmente, pensamos no TSO como uma sessão interativa acessada pelo terminal 3270. Porém, o IKJEFT01 cria uma espécie de sessão TSO sem uma pessoa digitando comandos.

Por meio dele, podemos executar:

  • comandos TSO;

  • CLIST;

  • execs REXX;

  • o command processor DSN;

  • alguns programas Db2;

  • comandos de execução de programas COBOL Db2.

No exemplo, ele recebe os comandos pelo DD:

//SYSTSIN DD *

O primeiro comando importante será:

DSN SYSTEM(DB9G)

Esse comando inicia o processador DSN e conecta o job ao subsistema Db2 chamado DB9G.

IKJEFT01 versus IKJEFT1B

Um detalhe interessante é que muitas instalações preferem:

PGM=IKJEFT1B

O IKJEFT1B é semelhante ao IKJEFT01, mas costuma ser escolhido em procedures nas quais a propagação do return code dos comandos internos precisa ser mais previsível.

Em uma esteira de build, isso é extremamente importante.

Imagine que o BIND falhou, mas o step terminou com retorno aparentemente aceitável. O pipeline poderia continuar, copiar o load module e declarar sucesso.

Resultado:

Load module novo
Package antigo

Na execução, aparece:

SQLCODE -818

Por isso, não basta olhar apenas o nome do programa executado. É preciso testar como a procedure trata códigos de retorno.


5. Entendendo COND=(4,LT,COB)

COND=(4,LT,COB)

A cláusula COND é uma das pegadinhas clássicas do JCL.

Ela não informa diretamente quando o step será executado. Ela informa quando o step deverá ser ignorado.

A expressão significa:

Se 4 for menor que o RC do step COB, não execute este step.

Em forma matemática:

4 < COB.RC

Tabela prática

RC do step COB4 menor que RC?Executa o BIND?
0NãoSim
4NãoSim
8SimNão
12SimNão
16SimNão

Portanto, o BIND será executado se o step COB retornar:

RC 0 ou RC 4

Isso faz sentido porque compiladores COBOL frequentemente usam:

RC 0 = compilação limpa
RC 4 = mensagens ou warnings aceitáveis
RC 8 = erro que impede uso seguro
RC 12+ = falha grave

Versão mais legível com IF

Uma alternativa moderna e mais fácil para iniciantes seria:

// IF COB.RC LE 4 THEN
//BINDPKG EXEC PGM=IKJEFT1B,DYNAMNBR=20
...
// ENDIF

Essa versão comunica diretamente a intenção:

Execute o bind se o retorno da compilação for menor ou igual a 4.

O COND é poderoso, mas sua lógica invertida provoca muitos erros de interpretação.


6. DYNAMNBR=20

DYNAMNBR=20

Esse parâmetro define uma quantidade de alocações dinâmicas que o ambiente TSO poderá administrar.

Durante a execução, o processador DSN e outros componentes podem precisar abrir datasets dinamicamente.

O valor 20 costuma ser suficiente para procedimentos simples.

Entretanto, em execuções mais complexas, encontramos:

DYNAMNBR=50

ou:

DYNAMNBR=100

Não existe mérito em aumentar esse número sem necessidade. Porém, um valor pequeno demais pode provocar falhas de alocação.

A regra é:

Use o valor padronizado pela instalação e ajuste apenas quando houver evidência de necessidade.


7. DBRMLIB: onde está o mapa SQL

//DBRMLIB DD DSN=&&DBRMDB2(COBDB501),DISP=(OLD,DELETE)

Esse DD aponta para o DBRM criado em uma etapa anterior.

Vamos desmontar a instrução.

DBRMLIB

É o DDNAME esperado pelo processo de BIND para localizar os DBRMs.

&&DBRMDB2

Os dois sinais de && indicam um dataset temporário criado dentro do job.

Ele provavelmente foi criado pelo precompiler com algo semelhante a:

//DBRMLIB DD DSN=&&DBRMDB2,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(5,5,5)),
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//            DSNTYPE=LIBRARY

O PASS indica que o dataset deve ser passado para outro step do mesmo job.

No step de BIND, ele é reutilizado.

(COBDB501)

Esse é o nome do membro contendo o DBRM.

Geralmente, o nome acompanha o programa:

Programa:    COBDB501
DBRM:        COBDB501
Package:     COBDB501
Load module: COBDB501

Essa padronização facilita:

  • pesquisa no catálogo;

  • leitura de spool;

  • manutenção;

  • comparação entre versões;

  • análise de problemas.

DISP=(OLD,DELETE)

OLD solicita acesso exclusivo ao dataset.

DELETE solicita sua remoção após o uso.

Isso é aceitável para um dataset temporário, mas existe um ponto de atenção.

Se o DBRM for apagado e não houver uma biblioteca permanente, uma falha posterior pode dificultar:

  • análise;

  • rebind;

  • comparação;

  • reconstrução do package;

  • rollback.

Em esteiras corporativas, o DBRM muitas vezes é preservado em uma biblioteca controlada por versão.


8. Uma possível redundância no DBRMLIB

O JCL usa:

DSN=&&DBRMDB2(COBDB501)

e o comando BIND usa:

MEMBER(COBDB501)

Ou seja, o membro está sendo indicado duas vezes.

O formato mais comum e flexível seria:

//DBRMLIB DD DSN=&&DBRMDB2,DISP=(OLD,DELETE)

E depois:

MEMBER(COBDB501)

Assim, DBRMLIB aponta para a biblioteca, enquanto MEMBER informa qual membro será processado.

Isso também permite executar vários binds com a mesma biblioteca:

BIND PACKAGE(APPPACK) MEMBER(PROGA)
BIND PACKAGE(APPPACK) MEMBER(PROGB)
BIND PACKAGE(APPPACK) MEMBER(PROGC)

9. Os DDs de saída

SYSUDUMP

//SYSUDUMP DD SYSOUT=*

Solicita um dump caso ocorra um abend.

O dump pode conter:

  • PSW;

  • registradores;

  • áreas de memória;

  • módulos carregados;

  • endereço da falha;

  • cadeia de chamadas.

Para erros comuns de BIND, normalmente você consultará primeiro o SYSTSPRT. Porém, se o processador sofrer um abend, SYSUDUMP pode ser indispensável.


SYSTSPRT

//SYSTSPRT DD SYSOUT=*

É a saída principal do ambiente TSO batch.

Nela aparecem:

  • mensagens do IKJEFT01;

  • mensagens do processador DSN;

  • confirmação da conexão;

  • mensagens de BIND;

  • return codes;

  • mensagens DSN;

  • erros de autorização;

  • packages criados ou substituídos.

Esta deve ser uma das primeiras saídas verificadas no SDSF.


SYSPRINT

//SYSPRINT DD SYSOUT=*

É uma saída genérica usada por diversos utilitários.

Dependendo da procedure, pode conter mensagens adicionais ou ficar praticamente vazia.

O importante para o iniciante é não assumir que todos os erros estarão em um único DD. Em incidentes, consulte:

JESMSGLG
JESJCL
JESYSMSG
SYSTSPRT
SYSPRINT
SYSUDUMP

10. SYSTSIN: os comandos começam aqui

//SYSTSIN DD *

O conteúdo abaixo é enviado como entrada para a sessão TSO batch.

O primeiro comando é:

DSN SYSTEM(DB9G)

Esse comando solicita conexão com o subsistema Db2 DB9G.

O identificador poderia representar:

DB9G = Db2 geração 9, ambiente G

ou qualquer convenção local.

Algumas empresas usam:

DB2D = desenvolvimento
DB2Q = qualidade
DB2P = produção

Outras usam códigos menos óbvios, especialmente em data sharing.

Um erro simples no SSID pode fazer o bind ocorrer no ambiente errado ou falhar completamente.

Imagine promover um package acreditando estar em homologação e descobrir que o SSID era o de produção. É por isso que procedures bem desenhadas recebem o subsistema por parâmetro:

// SET DB2SSID=DB9G

E depois:

DSN SYSTEM(&DB2SSID)

11. BIND PACKAGE(HERPACK)

BIND PACKAGE(HERPACK)

O nome entre parênteses representa a collection.

A collection é um agrupador lógico de packages.

Neste caso:

Collection: HERPACK
Package:    COBDB501

O package final será identificado conceitualmente como:

HERPACK.COBDB501

Collections podem representar:

  • uma aplicação;

  • um domínio;

  • uma versão;

  • um ambiente;

  • uma release;

  • uma equipe;

  • uma linha de negócio.

Exemplos:

FINANCEIRO
PAGAMENTOS
CADASTRO
APPV1
APPV2
HOMOLOG
PROD

Dica de arquitetura

Usar collections diferentes por versão pode facilitar rollback.

Exemplo:

APPV001.COBDB501
APPV002.COBDB501

O novo package pode ser preparado sem remover imediatamente o anterior.

Depois, o plan ou a estratégia de execução passa a usar a nova collection.

Isso é muito mais seguro do que substituir tudo sem possibilidade de retorno.


12. OWNER(INEFE00)

OWNER(INEFE00)

Define o authorization ID proprietário do package.

Esse owner pode influenciar:

  • propriedade;

  • administração;

  • autorizações;

  • resolução de privilégios;

  • auditoria;

  • governança.

Se INEFE00 for um usuário pessoal, isso merece atenção.

Imagine que a pessoa:

  • mudou de projeto;

  • saiu da empresa;

  • teve o usuário revogado;

  • perdeu privilégios;

  • teve o ID protegido por nova política.

Por isso, packages de produção geralmente deveriam pertencer a IDs funcionais, como:

APPDB2O
BINDUSER
FINOWNER
HEROWNR

O owner funcional reduz dependência de indivíduos.


13. MEMBER(COBDB501)

MEMBER(COBDB501)

Essa opção informa qual DBRM será utilizado.

O Db2 procurará o membro dentro da biblioteca indicada por:

//DBRMLIB

Se o membro não existir, o BIND falhará.

Antes de culpar o Db2, verifique:

  • o precompile foi executado?

  • o DBRM foi realmente criado?

  • o dataset foi passado com DISP=PASS?

  • o nome do membro está correto?

  • houve exclusão prematura do dataset?

  • o DBRMLIB aponta para a biblioteca correta?


14. ACTION(REP)

ACTION(REP)

REP significa REPLACE.

Isso informa:

Se o package já existir, substitua-o.

É uma opção comum em ambientes de desenvolvimento, mas precisa de cautela em produção.

Substituir um package pode alterar:

  • access path;

  • comportamento de locking;

  • consumo de CPU;

  • tempo de resposta;

  • dependências;

  • compatibilidade com o load module.

O package antigo pode ter sido extremamente estável. O novo BIND pode escolher um caminho de acesso diferente por causa de:

  • estatísticas atualizadas;

  • novo índice;

  • índice removido;

  • alteração de cardinalidade;

  • mudança de parâmetros;

  • nova versão do Db2;

  • mudança no catálogo.

Dica importante

Antes de substituir packages críticos, considere mecanismos de preservação e reutilização de access paths, além do gerenciamento de planos oferecido pelo Db2.

Em outras palavras:

Não trate ACTION(REPLACE) como um simples “salvar por cima”.


15. VALIDATE(BIND)

VALIDATE(BIND)

Solicita validação no momento do BIND.

Se o programa referencia:

SELECT NOME
  FROM CLIENTES;

o Db2 tentará verificar a existência e a validade dos objetos durante o bind.

Isso é positivo porque antecipa problemas.

Melhor descobrir durante o deploy que a tabela está ausente do que descobrir durante o fechamento financeiro.

A alternativa conhecida é:

VALIDATE(RUN)

Nesse caso, parte da validação pode ocorrer apenas quando a instrução for executada.

Comparação

OpçãoMomento da validaçãoPrincipal benefícioPrincipal risco
BINDDurante a implantaçãoFalha antecipadaExige ambiente pronto
RUNDurante a execuçãoMaior flexibilidadeErro pode aparecer em produção

Para programas batch tradicionais, VALIDATE(BIND) costuma ser uma escolha mais segura.


16. EXPLAIN(NO)

EXPLAIN(NO)

Indica que o BIND não deve gerar informações de EXPLAIN nas tabelas correspondentes.

O EXPLAIN ajuda a entender o caminho de acesso escolhido pelo otimizador.

Ele pode revelar:

  • table space scan;

  • index scan;

  • matching index;

  • nonmatching index;

  • sort;

  • prefetch;

  • ordem de join;

  • método de join;

  • paralelismo;

  • estimativas de custo.

Em desenvolvimento, EXPLAIN(YES) pode ser extremamente útil.

Por exemplo:

EXPLAIN(YES)

permite analisar por que um SQL está fazendo table scan mesmo com um índice aparentemente disponível.

Por que alguém usa EXPLAIN(NO)?

Possíveis razões:

  • reduzir geração de dados;

  • procedure antiga;

  • ambiente sem tabelas EXPLAIN configuradas;

  • processo separado de análise;

  • ferramenta externa de monitoramento;

  • package simples e já conhecido.

Entretanto, para SQL crítico, abrir mão completamente da análise de access path é arriscado.


17. DEGREE(1)

DEGREE(1)

Define grau de paralelismo igual a 1.

Em linguagem prática:

Execute sem paralelismo de query.

Isso pode ser apropriado para:

  • transações curtas;

  • consultas pequenas;

  • programas COBOL tradicionais;

  • workloads sensíveis ao consumo;

  • ambientes que desejam comportamento previsível.

Uma alternativa seria:

DEGREE(ANY)

permitindo que o Db2 avalie paralelismo.

Vantagem de DEGREE(1)

  • previsibilidade;

  • menor risco de consumo inesperado;

  • comportamento mais estável;

  • adequado a muitas transações OLTP.

Desvantagem

Consultas analíticas grandes podem demorar mais.

Não existe valor universalmente melhor. A escolha depende do workload.


18. ISO(UR): velocidade com risco

ISO(UR)

UR significa:

Uncommitted Read

É o nível de isolamento mais permissivo.

Ele pode permitir a leitura de dados ainda não confirmados por outra transação.

Exemplo:

Uma transação altera um saldo:

UPDATE CONTA
   SET SALDO = 100
 WHERE NUMERO = 999;

Mas ainda não executou COMMIT.

Um programa com UR pode enxergar o valor 100.

Depois, a transação executa:

ROLLBACK;

O dado lido nunca foi realmente confirmado.

Essa é a chamada leitura suja.

Quando UR pode ser aceitável?

  • relatório estatístico;

  • dashboard;

  • consulta aproximada;

  • monitoração;

  • dados sem impacto transacional;

  • leitura informativa.

Quando UR é perigoso?

  • saldo;

  • faturamento;

  • pagamento;

  • estoque;

  • contabilidade;

  • cálculo fiscal;

  • autorização de crédito;

  • tomada de decisão baseada em consistência.

Para muitos programas COBOL corporativos, CS pode ser uma opção mais equilibrada:

ISOLATION(CS)

CS significa Cursor Stability.

O grande conselho é:

Nunca copie ISO(UR) de outro JCL sem entender a regra de negócio.


19. ENABLE(*)

ENABLE(*)

Essa cláusula está associada à habilitação do package para contextos de conexão suportados.

O asterisco representa uma habilitação ampla.

Ela pode ser conveniente em procedures genéricas, mas vale avaliar se o package realmente precisa estar habilitado para todos os contextos aplicáveis.

A lógica de segurança é semelhante ao princípio do menor privilégio:

Habilite apenas o necessário.

Em muitas instalações, esse detalhe é controlado por padrões corporativos e deve ser validado com o DBA.


20. ENCODING(EBCDIC)

ENCODING(EBCDIC)

Define EBCDIC como encoding do package.

Isso é natural para muitos programas COBOL executados em z/OS.

Porém, encoding não é um detalhe cosmético.

Ele afeta:

  • caracteres acentuados;

  • conversão de strings;

  • integração com ASCII;

  • Unicode;

  • APIs;

  • XML;

  • JSON;

  • Java;

  • clientes distribuídos.

Imagine os caracteres:

ã
é
ç

Em ambientes com conversão incorreta, eles podem virar símbolos estranhos ou provocar erros de conversão.

Quando uma aplicação COBOL conversa com sistemas distribuídos, é necessário observar:

  • CCSID das tabelas;

  • CCSID da aplicação;

  • encoding do package;

  • encoding da conexão;

  • formato dos dados recebidos.


21. BIND PLAN(HERP0001)

BIND PLAN(HERP0001)

Depois do package, o JCL cria ou substitui um plan chamado:

HERP0001

O plan fornece um contexto de execução e referencia packages.

Visualmente:

PLAN HERP0001
    |
    +-- HERPACK.COBDB501
    +-- HERPACK.COBDB502
    +-- HERPACK.COBDB503

Historicamente, plans tinham um papel ainda mais central. Com a adoção de packages, passou a ser comum pensar assim:

DBRM → PACKAGE
PLAN → lista de packages

22. PKLIST e a possível redundância

PKLIST(HERPACK.*,HERPACK.COBDB501)

A PKLIST informa onde o plan deverá procurar packages.

A entrada:

HERPACK.*

significa, de forma geral:

Packages da collection HERPACK

A entrada:

HERPACK.COBDB501

indica especificamente o package COBDB501.

O problema é que:

HERPACK.*

aparentemente já cobre:

HERPACK.COBDB501

Portanto, há uma possível redundância.

Para um plan exclusivo:

PKLIST(HERPACK.COBDB501)

Para um plan compartilhado:

PKLIST(HERPACK.*)

A lista original pode ter sido criada por:

  • geração automática;

  • procedure antiga;

  • manutenção parcial;

  • tentativa de reforçar a resolução;

  • simples excesso de cautela.

Mesmo quando algo funciona, vale perguntar:

Está claro, necessário e fácil de manter?


23. Um JCL completo de precompile, compile, link e bind

A seguir, um exemplo educacional simplificado.

Passo 1 — Precompile

//PRECOMP EXEC PGM=DSNHPC,
//             PARM='HOST(IBMCOB),APOST,SQL'
//STEPLIB  DD DISP=SHR,DSN=DB2.SDSNLOAD
//SYSIN    DD DISP=SHR,DSN=ALUNO.COBOL(COBDB501)
//SYSCIN   DD DSN=&&COBSRC,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(10,5)),
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//DBRMLIB  DD DSN=&&DBRMDB2,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(5,5,5)),
//            DSNTYPE=LIBRARY,
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSPRINT DD SYSOUT=*
//SYSTERM  DD SYSOUT=*

O que acontece?

  • DSNHPC executa o precompiler.

  • SYSIN contém o fonte COBOL com SQL.

  • SYSCIN recebe o fonte COBOL modificado.

  • DBRMLIB recebe o DBRM.

  • SYSPRINT recebe mensagens.


Passo 2 — Compile

//COB EXEC PGM=IGYCRCTL,
//         PARM='LIB,OBJECT,LIST,MAP,XREF'
//SYSIN    DD DSN=&&COBSRC,DISP=(OLD,DELETE)
//SYSLIN   DD DSN=&&OBJ,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(10,5)),
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSLIB   DD DISP=SHR,DSN=DB2.SDSNMACS
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT2   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT3   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT4   DD UNIT=SYSDA,SPACE=(CYL,(1,1))

O que acontece?

  • IGYCRCTL executa o compilador COBOL.

  • SYSIN recebe o fonte alterado pelo precompiler.

  • SYSLIN recebe o object module.

  • SYSPRINT contém a listagem.


Passo 3 — Link-edit

//LKED EXEC PGM=IEWL,
//         PARM='LIST,XREF,LET,MAP'
//SYSLIN   DD DSN=&&OBJ,DISP=(OLD,DELETE)
//         DD DISP=SHR,DSN=DB2.SDSNLOAD(DSNELI)
//SYSLMOD  DD DISP=SHR,DSN=ALUNO.LOADLIB(COBDB501)
//SYSLIB   DD DISP=SHR,DSN=CEE.SCEELKED
//SYSPRINT DD SYSOUT=*
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(1,1))

O que acontece?

  • IEWL executa o binder/link-editor.

  • SYSLIN recebe o object module.

  • O módulo de interface Db2 é incluído conforme o tipo de execução.

  • SYSLMOD recebe o load module final.


Passo 4 — Bind package e plan

// IF COB.RC LE 4 THEN
//BIND EXEC PGM=IKJEFT1B,DYNAMNBR=20
//STEPLIB  DD DISP=SHR,DSN=DB2.SDSNLOAD
//DBRMLIB  DD DSN=&&DBRMDB2,DISP=(OLD,DELETE)
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN  DD *
 DSN SYSTEM(DB9G)

 BIND PACKAGE(HERPACK)          -
      MEMBER(COBDB501)          -
      OWNER(HEROWNR)            -
      ACTION(REPLACE)           -
      VALIDATE(BIND)            -
      EXPLAIN(YES)              -
      DEGREE(1)                 -
      ISOLATION(CS)             -
      ENCODING(EBCDIC)

 BIND PLAN(HERP0001)            -
      PKLIST(HERPACK.COBDB501)  -
      ACTION(REPLACE)           -
      ISOLATION(CS)             -
      ENCODING(EBCDIC)

 END
/*
// ENDIF

Observe as melhorias:

  • uso de IF;

  • IKJEFT1B;

  • biblioteca inteira em DBRMLIB;

  • owner funcional;

  • EXPLAIN(YES);

  • isolamento CS;

  • PKLIST sem redundância;

  • comando END explícito.


24. JCL de execução

Depois da construção, o programa poderia ser executado assim:

//RUNDB2 EXEC PGM=IKJEFT1B,DYNAMNBR=20
//STEPLIB  DD DISP=SHR,DSN=ALUNO.LOADLIB
//         DD DISP=SHR,DSN=DB2.SDSNLOAD
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN  DD *
 DSN SYSTEM(DB9G)

 RUN PROGRAM(COBDB501)          -
     PLAN(HERP0001)             -
     LIB('ALUNO.LOADLIB')

 END
/*

O fluxo será:

RUN PROGRAM(COBDB501)
          ↓
Load module COBDB501
          ↓
PLAN HERP0001
          ↓
PKLIST
          ↓
PACKAGE HERPACK.COBDB501
          ↓
Execução das instruções SQL

25. Erros comuns e soluções

SQLCODE -805

O -805 geralmente indica que o package necessário não foi encontrado ou não corresponde ao contexto procurado.

Possíveis causas:

  • package não bindado;

  • collection errada;

  • plan com PKLIST incorreta;

  • subsistema errado;

  • package removido;

  • load module de outro ambiente;

  • versão inexistente;

  • consistency token incompatível.

Checklist

1. O BIND PACKAGE terminou com sucesso?
2. A collection é HERPACK?
3. O package é COBDB501?
4. O plan HERP0001 inclui essa collection?
5. A execução está no subsistema DB9G?
6. O load module pertence ao mesmo build?
7. O package foi substituído depois do link?

Solução típica

Refazer o build completo:

Precompile
Compile
Link
Bind package
Bind plan
Deploy

Evite refazer apenas uma etapa sem saber exatamente o motivo.


SQLCODE -818

O -818 normalmente indica inconsistência entre o programa e o package.

Em termos didáticos:

Load module versão A
Package versão B

Isso acontece quando:

  • o programa foi recompilado e não houve novo bind;

  • o package foi substituído, mas o load module não;

  • houve deploy parcial;

  • o DBRM usado não pertence ao objeto compilado;

  • arquivos de builds diferentes foram misturados.

Solução

Reconstruir e promover os artefatos juntos.

Pense no load module e no package como irmãos gêmeos de build. Separá-los é pedir confusão.


Erro de autorização

O usuário do job pode não possuir:

  • privilégio de BIND;

  • autorização sobre a collection;

  • autorização para usar o owner;

  • acesso aos objetos SQL;

  • autorização de replace;

  • privilégio para criar o plan.

Solução

Consultar mensagens no SYSTSPRT e trabalhar com o DBA ou segurança.

Não resolva concedendo privilégios amplos sem análise.

O correto é identificar precisamente o privilégio necessário.


DBRM não encontrado

Possíveis causas:

  • erro no nome do membro;

  • precompile falhou;

  • DISP=PASS ausente;

  • dataset temporário deletado;

  • DD apontando para biblioteca errada;

  • membro indicado duas vezes de forma problemática;

  • job reiniciado a partir do step de BIND, mas o dataset temporário já não existe.

Solução

Use uma biblioteca permanente de DBRMs quando o processo precisar suportar restart independente.

Dataset temporário desaparece ao final do job. Portanto, reiniciar apenas o step de BIND em outro job pode não funcionar.


Objetos inexistentes

Com VALIDATE(BIND), tabelas ou views ausentes podem causar falha.

Possíveis causas:

  • ambiente incompleto;

  • DDL não aplicado;

  • qualificador incorreto;

  • tabela criada em outro schema;

  • alias ausente;

  • deploy executado fora de ordem.

Solução

Aplicar primeiro as mudanças de banco e depois executar o BIND.

Uma esteira madura respeita dependências:

DDL
RUNSTATS quando necessário
BIND
Deploy do executável
Execução

Access path pior após o BIND

O BIND pode escolher um caminho de acesso diferente.

Sintomas:

  • maior CPU;

  • mais GETPAGE;

  • batch mais lento;

  • aumento de I/O;

  • timeout;

  • lock escalation;

  • duração imprevisível.

Causas:

  • estatísticas desatualizadas;

  • mudança de índice;

  • alteração de cardinalidade;

  • parâmetros diferentes;

  • novo release;

  • BIND executado após mudanças no catálogo.

Soluções

  • executar RUNSTATS adequadamente;

  • usar EXPLAIN;

  • comparar access paths;

  • preservar opções de estabilidade;

  • testar antes da produção;

  • monitorar packages críticos;

  • usar mecanismos de gerenciamento de planos.


26. Como otimizar o processo

1. Padronize opções de BIND

Não permita que cada programador invente suas próprias opções.

Crie procedures corporativas para:

  • batch;

  • CICS;

  • IMS;

  • programas de consulta;

  • programas críticos;

  • packages distribuídos.


2. Use owners funcionais

Evite IDs pessoais em produção.


3. Versione packages e collections

Isso facilita rollback e coexistência entre releases.


4. Preserve os DBRMs

Principalmente em ambientes com auditoria, rebind ou recuperação.


5. Use EXPLAIN de forma consciente

Não espere uma crise de performance para descobrir o access path.


6. Monitore o RC real do BIND

O pipeline precisa falhar quando o BIND falhar.

“Job terminou” não significa “package válido”.


7. Evite UR por hábito

Escolha o isolamento conforme a regra de negócio.


8. Elimine redundâncias

Uma PKLIST limpa é mais fácil de auditar.


9. Mantenha compile, link e bind na mesma unidade de mudança

Essa é uma das melhores formas de evitar -805 e -818.


10. Planeje rollback

Antes de substituir um package, responda:

Como volto à versão anterior?

Se ninguém souber responder, o deploy ainda não está pronto.


27. Dicas para o programador COBOL iniciante

Quando um programa Db2 falhar, não olhe apenas o fonte COBOL.

Investigue a cadeia completa:

Fonte
Precompile
DBRM
Compile
Object
Link
Load module
Package
Collection
Plan
PKLIST
Subsistema
Autorização

Aprenda a ler mensagens no spool. Muitas respostas estão no SYSTSPRT, mas o iniciante frequentemente olha apenas o MAXCC.

Nunca suponha que RC=0 em um step significa que todos os comandos internos tiveram sucesso. Verifique as mensagens e a forma como os retornos são propagados.

Não copie opções de BIND cegamente. Cada uma carrega uma decisão:

UR
CS
RR
DEGREE
VALIDATE
EXPLAIN
OWNER
ENCODING
ACTION

Toda opção deveria conseguir responder à pergunta:

Por que estamos usando isso?

Se a única resposta for “sempre foi assim”, há uma dívida técnica escondida.


28. Easter egg: o package é a memória Jedi do SQL

Existe uma analogia divertida para guardar esse fluxo.

O fonte COBOL é o Padawan.

O DBRM é o pergaminho contendo as técnicas SQL aprendidas.

O BIND é o Conselho que examina o pergaminho, verifica permissões e escolhe como cada técnica será executada.

O package é o Holocron pronto para uso.

O plan é a autorização de missão que informa quais Holocrons o Padawan pode consultar.

Quando ocorre -805, o guerreiro chegou à missão, mas o Holocron não estava na lista.

Quando ocorre -818, ele trouxe um Holocron de outra geração.

E quando alguém usa ISO(UR) em um sistema financeiro sem entender o motivo, é como desligar os escudos para ganhar velocidade.

Pode funcionar.

Até o momento em que não funciona.


Conclusão

O JCL de BIND é uma das peças mais importantes do ciclo de construção de um programa COBOL Db2.

Ele não é apenas um passo burocrático depois da compilação.

É nele que o Db2 recebe o DBRM, valida objetos, verifica autorizações, prepara as instruções SQL, cria o package e associa esse package ao contexto de execução fornecido pelo plan.

O fluxo completo é:

COBOL com SQL
      ↓
Precompile
      ↓
DBRM + fonte modificado
      ↓
Compile
      ↓
Object module
      ↓
Link-edit
      ↓
Load module
      ↓
BIND PACKAGE
      ↓
Package
      ↓
BIND PLAN
      ↓
Execução

No exemplo analisado:

DBRM:       COBDB501
Collection: HERPACK
Package:    HERPACK.COBDB501
Plan:       HERP0001
Subsistema: DB9G

O JCL funciona como uma ponte entre o mundo executável do COBOL e o mundo relacional do Db2.

Entretanto, ele também revela diversos pontos para melhoria:

  • avaliar IKJEFT1B;

  • usar IF para maior clareza;

  • remover redundância no DBRMLIB;

  • usar owner funcional;

  • revisar ISO(UR);

  • eliminar redundância na PKLIST;

  • considerar EXPLAIN(YES);

  • planejar rollback;

  • preservar DBRMs;

  • garantir sincronização entre package e load module.

O programador que domina o BIND deixa de tratar -805 e -818 como magia obscura.

Ele passa a enxergar exatamente onde cada artefato nasceu, como foi preparado, qual plan o referencia e por que o Db2 aceitou ou rejeitou sua execução.

E essa é uma das passagens mais importantes na jornada de um COBOL Padawan:

Compreender que compilar o programa cria o corpo, mas executar o BIND prepara a inteligência SQL que permite ao programa conversar com o coração do Db2.

Sem comentários:

Enviar um comentário