☕ 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 IRLM. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta IRLM. Mostrar todas as mensagens

quinta-feira, 7 de março de 2024

Mr. Spock Entra no CPD — O Dia em que o Programador COBOL Disse “É Só um SELECT” e Descobriu uma Civilização Inteira Dentro do Db2

 

Bellacosa Mainframe por dentro do Db2

☕ Um Café no Bellacosa Mainframe

Mr. Spock Entra no CPD — O Dia em que o Programador COBOL Disse “É Só um SELECT” e Descobriu uma Civilização Inteira Dentro do Db2

Ou: por que Buffer Pool, IRLM, DDF, Catalog, Directory, Logs, RUNSTATS, Package, RACF, WLM e Parallel Sysplex fazem parte da mesma missão — e por que dizer que Db2 é “apenas um banco de dados” seria, segundo Spock, altamente ilógico

O turno da noite estava tranquilo.

Tranquilo demais.

E todo profissional de mainframe com alguma estrada sabe que essa frase normalmente é seguida por algum desastre.

O monitor do CICS estava verde. O JES2 aparentemente não tinha nada contra a humanidade naquele momento. O RACF não estava distribuindo ICH408I como panfleto em estação de metrô e nenhum operador havia entrado correndo no CPD gritando:

— A PRODUÇÃO PAROU!

Era quase suspeito.

O jovem programador COBOL, ainda naquela fase da carreira em que acreditamos que um programa que compilou também necessariamente funciona, olhou para sua rotina e anunciou:

EXEC SQL
   SELECT NOME,
          SALDO
     INTO :WS-NOME,
          :WS-SALDO
     FROM CLIENTE
    WHERE CONTA = :WS-CONTA
END-EXEC.

Ele sorriu.

— Pronto. É só um SELECT.

Uma sobrancelha levantou-se no outro lado da sala.

Mr. Spock havia entrado no CPD.

Ninguém soube explicar como um oficial científico da Frota Estelar havia conseguido autorização RACF, crachá temporário e acesso à área restrita do datacenter. Mas considerando que o pessoal de infraestrutura já havia liberado consultores externos com justificativas muito piores, ninguém perguntou.

Spock examinou o código.

Depois examinou o programador.

— Sua afirmação contém uma simplificação estatisticamente perigosa.

— Como assim?

— Você acredita ter executado um SELECT. Na realidade, iniciou uma sequência de eventos envolvendo processamento SQL, gerenciamento de memória, otimização, concorrência, storage, catálogo, controle transacional, autorização e possivelmente comunicação distribuída.

O programador ficou olhando para ele.

— Mas voltou um saldo.

— Exatamente. E esta é a parte fascinante.

Assim começa nossa viagem pela arquitetura do Db2 for z/OS.



1. Primeiro diagnóstico de Spock: Db2 não é uma caixa preta

Para muita gente que começa no COBOL, Db2 parece funcionar assim:

COBOL
  ↓
SQL
  ↓
Db2
  ↓
dados

É confortável.

Também está incompleto.

Uma representação mais próxima da realidade seria algo como:

Programa COBOL
      ↓
CICS / Batch / DDF
      ↓
Thread Db2
      ↓
Package
      ↓
Access Path
      ↓
DBM1
      ↓
Buffer Pools
      ↓
Table Space / Index Space
      ↓
DFSMS / Storage

Enquanto isso, paralelamente:

IRLM → locking
Logs → recovery
RACF → segurança
WLM → prioridade
Catalog → metadados
DDF → acesso distribuído

Spock provavelmente resumiria:

“A simplicidade percebida pelo programador é consequência da complexidade absorvida pela infraestrutura.”

E isso é um dos maiores triunfos do mainframe.



2. O que é um Db2 Subsystem?

Vamos começar pela porta da nave.

No z/OS, frequentemente trabalhamos com um Db2 subsystem.

Ele representa uma instância operacional do Db2 dentro daquele ambiente.

Uma empresa poderia ter algo como:

DB2D → desenvolvimento
DB2T → testes
DB2H → homologação
DB2P → produção

Os nomes variam conforme a instalação.

Não existe mandamento dizendo que produção precisa se chamar DB2P.

Aliás, se existe algo que mainframe ensina rapidamente é:

cada empresa tem suas tradições.

Algumas parecem normas técnicas.

Outras parecem decisões tomadas em 1989 por alguém chamado Geraldo, que se aposentou em 2003 e nunca documentou nada.

Curiosidade do CPD

É muito comum o iniciante dizer:

— Estou conectado no Db2.

O veterano pergunta:

— Qual?

E aí começa a aula.

Um mesmo ambiente pode possuir múltiplos subsystems.

Por isso entender onde seu programa está executando é tão importante quanto entender o que ele executa.



3. DBM1 — a sala de máquinas

No coração da arquitetura encontramos o DBM1, o Database Services Address Space.

É onde ocorre uma quantidade enorme do trabalho relacionado ao banco.

Dentro dessa paisagem aparecem conceitos como:

  • Buffer Pools;

  • EDM Pool;

  • estruturas de processamento;

  • threads;

  • acesso a dados;

  • gerenciamento interno;

  • execução de SQL.

Pense no DBM1 como a engenharia da Enterprise.

Você pode estar sentado confortavelmente na ponte dizendo:

— Warp 5.

Mas alguém lá embaixo precisa fazer o motor funcionar.

No COBOL seria:

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

Do ponto de vista do desenvolvedor:

SELECT → resultado

Do ponto de vista da infraestrutura:

solicitação
→ contexto de execução
→ access path
→ memória
→ índice
→ páginas
→ locking
→ eventualmente I/O
→ retorno

“É só um SELECT” começa a parecer uma frase corajosa.


4. Buffer Pool — o truque que evita transformar cada consulta em uma excursão ao storage

Se existe um conceito que todo programador Db2 deveria entender cedo, é Buffer Pool.

Imagine que você tenha uma tabela com 100 milhões de registros.

O programa procura:

SELECT NOME
FROM CLIENTE
WHERE ID_CLIENTE = 928173;

Fisicamente, os dados estão persistidos em storage.

Se toda consulta tivesse que buscar diretamente no disco, teríamos:

programa
   ↓
Db2
   ↓
storage
   ↓
I/O
   ↓
Db2
   ↓
programa

Constantemente.

A performance seria digna de uma carroça klingon.

O Buffer Pool existe justamente para manter páginas de dados e índices em memória.

              MEMÓRIA

        ┌───────────────────┐
        │    BUFFER POOL    │
        │                   │
        │ páginas de dados  │
        │ páginas de índice │
        └─────────┬─────────┘
                  │
          página ausente?
                  │
              SIM ↓
               STORAGE

Se a página já está em memória, evitamos determinado I/O físico.

Essa diferença pode ser gigantesca.


5. O programador pensa em linha; o Db2 frequentemente pensa em página

Aqui está uma mudança de mentalidade poderosa.

O programador escreve:

WHERE CONTA = 12345

Ele pensa:

“Quero essa linha.”

O Db2 precisa lidar com estruturas de armazenamento organizadas em pages.

Então conceitualmente:

linha solicitada
      ↓
página onde ela está
      ↓
Buffer Pool
      ↓
storage se necessário

Isso explica por que performance de banco não pode ser estudada pensando apenas no SQL textual.

Existem questões envolvendo:

  • número de páginas;

  • organização dos dados;

  • índices;

  • clustering;

  • seletividade;

  • Buffer Pool;

  • I/O;

  • estatísticas.

Spock talvez acrescentasse:

— Confundir linha lógica com armazenamento físico seria ilógico.

O DBA responderia:

— Finalmente alguém me entende.


6. Table Space — onde a tabela mora

Uma tabela Db2 precisa viver em uma estrutura apropriada de armazenamento.

Entra o Table Space.

Podemos visualizar:

DATABASE
   │
   ├── TABLE SPACE
   │      │
   │      └── TABLE
   │
   └── INDEX SPACE
          │
          └── INDEX

Aqui vale uma distinção importante.

Table Space e Index Space não são exatamente a mesma coisa.

A tabela reside no Table Space.

O índice possui sua própria estrutura associada.

Essa diferença aparece bastante quando começamos a estudar:

  • utilities;

  • administração;

  • recovery;

  • reorganização;

  • performance.


7. Índice — o tricorder do Db2

Imagine um arquivo com 20 milhões de clientes.

Você quer:

SELECT *
FROM CLIENTE
WHERE CPF = '12345678900';

Sem um caminho adequado, o Db2 pode precisar examinar uma grande quantidade de dados.

Com um índice apropriado:

CPF procurado
    ↓
ÍNDICE
    ↓
localização das páginas
    ↓
dados

Parece maravilhoso.

E é.

Mas existe uma regra que iniciantes aprendem um pouco depois:

índice não é almoço grátis.

Cada índice pode representar:

  • armazenamento;

  • manutenção;

  • custo em INSERT;

  • custo em UPDATE;

  • custo em DELETE;

  • necessidade de reorganização;

  • estatísticas;

  • complexidade adicional.

Criar índice para absolutamente tudo seria como equipar cada tripulante da Enterprise com quinze tricorders.

Em algum momento alguém precisa carregar aquilo.


8. O Optimizer — Spock trabalhando dentro do Db2

Talvez nenhum componente mereça mais o título de “Mr. Spock interno” do que o optimizer.

Você escreve:

SELECT C.NOME,
       P.VALOR
FROM CLIENTE C
JOIN PAGAMENTO P
  ON P.ID_CLIENTE = C.ID_CLIENTE
WHERE C.UF = 'SP';

Você disse o que deseja.

Mas existe mais de uma maneira de conseguir aquilo.

O Db2 pode precisar decidir:

  • qual tabela acessar primeiro;

  • qual índice usar;

  • se deve usar índice;

  • método de join;

  • ordem das tabelas;

  • custo estimado;

  • paralelismo;

  • quantidade provável de linhas.

Esse conjunto de decisões produz o chamado access path.

Simplificando:

SQL
 ↓
Optimizer
 ↓
estatísticas
 ↓
custos estimados
 ↓
Access Path
 ↓
execução

É por isso que dois SQLs que entregam exatamente o mesmo resultado podem ter performances completamente diferentes.


9. RUNSTATS — não mande Spock calcular com sensores quebrados

O optimizer precisa tomar decisões.

Mas baseado em quê?

Em informações sobre os objetos e os dados.

Entram aí as statistics.

Imagine esta distribuição:

CLIENTE

SP = 5.000.000
RJ = 2.000.000
MG = 1.500.000
AC =    30.000
RR =    20.000

Agora compare:

WHERE UF = 'SP'

com:

WHERE UF = 'RR'

A seletividade pode ser radicalmente diferente.

O optimizer precisa ter noção disso.

Ferramentas como RUNSTATS ajudam a coletar estatísticas utilizadas nas decisões de otimização.

Metáfora Bellacosa

Imagine Spock calculando a rota até Vulcano.

Mas você fornece um mapa feito antes da construção das últimas cinquenta colônias.

Ele continua sendo brilhante.

Só está usando informação ruim.

Em banco de dados:

optimizer bom + estatística ruim = possibilidade de access path ruim.

Por isso performance não é apenas:

— “Reescreve esse SELECT.”

Às vezes o SQL estava perfeitamente aceitável.

O ambiente é que mudou.


10. EDM Pool — aquilo que não queremos reconstruir a toda hora

Outro componente importante é o EDM Pool — Environmental Descriptor Manager Pool.

Ele mantém estruturas importantes usadas pelo Db2, incluindo informações relacionadas a packages e estruturas de execução.

O conceito pedagógico é simples:

aquilo que custa processamento para construir pode ser vantajoso manter disponível em memória.

Não confunda EDM Pool com Buffer Pool.

O Buffer Pool trabalha fortemente com páginas de dados e índices.

O EDM Pool está associado a outras estruturas internas necessárias à execução.

Mas ambos ilustram uma obsessão saudável de sistemas de alta performance:

evitar trabalho desnecessário.


11. IRLM — ninguém toca nesse registro sem conversar com o segurança

Chegamos ao IRLM — Internal Resource Lock Manager.

O problema que ele ajuda a resolver é clássico.

Imagine:

Programa A

UPDATE CONTA
SET SALDO = 500
WHERE CONTA = 100;

Programa B

simultaneamente:

UPDATE CONTA
SET SALDO = 800
WHERE CONTA = 100;

Quem ganha?

Quem espera?

Quem pode ler?

Em qual momento?

Que isolamento estamos usando?

Sem controle de concorrência, banco de dados financeiro viraria bingo.

O IRLM participa do gerenciamento de locks.

Podemos pensar:

Programa A ─────┐
                ├── IRLM ── recurso
Programa B ─────┘

Locks existem para preservar consistência em ambientes concorrentes.

E ambiente mainframe costuma ser sinônimo de concorrência em escala bastante séria.


12. Deadlock — quando dois oficiais se recusam a sair da porta

Considere:

Programa A tem recurso X
Programa B tem recurso Y

Agora:

A precisa de Y
B precisa de X

Resultado:

A ───── espera por Y
↑                 │
│                 ↓
X espera por ───── B

Temos um deadlock.

Os dois ficariam esperando eternamente se o sistema não identificasse a situação.

O Db2 precisa detectar o problema e selecionar uma unidade de trabalho para ser interrompida.

Dica para COBOL iniciante

Quando ocorrer erro associado a deadlock ou timeout, não trate imediatamente como:

“Db2 caiu.”

Não.

Na maioria das vezes Db2 está vivíssimo.

Talvez vivo até demais.

Está protegendo a consistência contra seus programas.


13. LOCK não é LATCH

Esse é um pequeno easter egg técnico para quando você estiver conversando com alguém mais experiente.

Lock e latch não são sinônimos.

Locks estão fortemente associados ao controle lógico/transacional de concorrência.

Latches são mecanismos internos de serialização mais leves usados para proteger determinadas estruturas internas.

Portanto quando alguém disser:

— Temos contenção.

Pergunte:

— Que tipo?

Você ganhará pelo menos +3 pontos de experiência mainframe.

Talvez até um café.


14. Logs — a caixa-preta da Enterprise

Agora entramos em uma das áreas mais importantes do Db2.

Imagine:

UPDATE CONTA
SET SALDO = SALDO - 100
WHERE NUM_CONTA = 123;

Uma alteração aconteceu.

O sistema precisa ter capacidade de preservar consistência e recuperar-se de falhas.

Por isso existe toda uma arquitetura de logging.

Em uma visão simplificada:

alteração
   ↓
Log Buffer
   ↓
Active Logs
   ↓
Archive Logs

Os logs guardam informações fundamentais para:

  • recovery;

  • rollback;

  • restart;

  • consistência transacional.

Sem logs, um banco corporativo seria praticamente um caderno escrito a lápis durante um terremoto.


15. COMMIT — quatro letras e uma enorme responsabilidade

No COBOL:

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

EXEC SQL
   COMMIT
END-EXEC.

COMMIT não significa simplesmente:

“terminei.”

Ele marca uma fronteira transacional importante.

Imagine:

UPDATE
INSERT
DELETE
UPDATE
   ↓
COMMIT

A unidade de trabalho foi confirmada.

O gerenciamento correto de commit é particularmente importante em batch.

Por quê?

Imagine processar cinco milhões de registros e só dar COMMIT no final.

Isso pode aumentar:

  • volume de locks;

  • duração de locks;

  • quantidade de trabalho a desfazer;

  • impacto de rollback;

  • pressão operacional.

Por outro lado, dar COMMIT a cada registro também pode ser inadequado.

A frequência de commit deve ser desenhada conscientemente.

Não existe “número mágico universal”.


16. ACID — as quatro leis de Vulcano das transações

O Db2 trabalha sob princípios transacionais tradicionalmente descritos pela sigla ACID.

Atomicity

Ou a unidade de trabalho ocorre adequadamente ou precisamos impedir resultado parcial inconsistente.

Consistency

O banco deve passar de um estado válido para outro.

Isolation

Transações concorrentes precisam coexistir de forma controlada.

Durability

Depois de confirmado, o resultado deve sobreviver conforme as garantias do sistema.

Considere uma transferência:

Conta Kirk  -100
Conta Spock +100

O universo proibido seria:

Conta Kirk  -100

💥 falha

Conta Spock +0

O dinheiro sumiu em algum buraco de minhoca.

O banco central provavelmente não aceitaria “anomalia espaço-temporal” como justificativa.


17. Active Log, Archive Log e a arte de voltar no tempo sem DeLorean

Os Active Logs participam diretamente das operações correntes de logging do Db2.

Com o avanço do processamento, parte dessas informações pode ser arquivada em Archive Logs.

Conceitualmente:

atividade recente
       ↓
Active Logs
       ↓
arquivamento
       ↓
Archive Logs

Essa arquitetura é um dos pilares das capacidades de recovery.

E aqui entra outro personagem importante.


18. IMAGE COPY — a fotografia antes da tempestade

Uma Image Copy funciona como uma cópia utilizada em estratégias de recuperação dos objetos Db2.

Imagine:

00:00
IMAGE COPY
   │
   │ logs
   │ logs
   │ logs
   │
13:42
falha

Dependendo da estratégia e do cenário, combinamos:

IMAGE COPY
+
LOGS
+
procedimento de recovery

para reconstruir o estado necessário.

Isso é muito mais sofisticado do que aquela frase genérica:

“Restauramos o backup.”

Em ambientes grandes, recovery é ciência.


19. Catalog — o cartório galáctico

Imagine que você cria:

CREATE TABLE PLANETA
(
   ID_PLANETA INTEGER,
   NOME       VARCHAR(80),
   QUADRANTE  CHAR(1)
);

Db2 precisa saber:

  • que a tabela existe;

  • quais colunas existem;

  • seus tipos;

  • seus índices;

  • seus relacionamentos;

  • tablespace;

  • authorities;

  • estatísticas;

  • dependências.

Essas informações vivem no universo do Db2 Catalog.

A metáfora é simples:

Os dados são cidadãos.
O Catalog é o cartório.

Quer saber sobre determinado objeto?

Frequentemente você consulta tabelas do catálogo.


20. Directory — o compartimento em que Spock recomenda não mexer sem motivo

Além do Catalog existe o Db2 Directory.

São estruturas internas essenciais ao próprio funcionamento do Db2.

Uma distinção simplificada:

CATALOG
→ metadados administrativos acessíveis

DIRECTORY
→ estruturas internas do próprio Db2

Não trate os dois termos como sinônimos.

É uma daquelas diferenças que parece acadêmica no começo.

Depois você começa a estudar internals e percebe por que existia.


21. DDF — o momento em que o mainframe abre as portas da nave

Db2 for z/OS não serve apenas a COBOL rodando dentro do próprio mainframe.

Aplicações externas podem acessar Db2 utilizando DDF — Distributed Data Facility.

Por exemplo:

Java
Python
.NET
Linux
Windows
Cloud
   │
   ↓
DRDA
   ↓
TCP/IP
   ↓
DDF
   ↓
Db2 for z/OS

Isso destrói outro mito antigo:

“Mainframe é uma ilha.”

Há décadas não é.

O mainframe moderno pode conversar com praticamente o ecossistema corporativo inteiro.


22. DRDA — o diplomata entre mundos relacionais

DRDA — Distributed Relational Database Architecture fornece mecanismos padronizados para acesso distribuído a bancos relacionais.

Você pode imaginar:

Aplicação externa
      ↓
Driver
      ↓
DRDA
      ↓
TCP/IP
      ↓
DDF
      ↓
Db2

Ou seja, aquele programa Java no Kubernetes pode estar consultando informações que no final vivem no Db2 for z/OS.

O desenvolvedor Java talvez nem saiba.

E em muitos casos nem precisa saber.

Mas o arquiteto deveria.


23. COBOL + CICS + Db2 — o triângulo clássico

Agora voltamos à nossa velha sala de produção.

Um caminho clássico:

usuário
   ↓
CICS
   ↓
Programa COBOL
   ↓
SQL
   ↓
Db2

No programa:

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

Parece natural.

Mas como o SQL foi parar dentro daquele programa executável?

Aí vem uma parte fundamental que muitos cursos passam rápido demais.


24. PRECOMPILE — COBOL e SQL precisam conversar

COBOL puro não interpreta nativamente aquele EXEC SQL.

Existe uma etapa de preparação.

De forma tradicional e simplificada:

Fonte COBOL + SQL
        ↓
   PRECOMPILER
      ┌─┴─────────────┐
      ↓               ↓
COBOL modificado     DBRM
      ↓               ↓
Compiler             BIND
      ↓               ↓
Object              Package
      ↓
Link
      ↓
Load Module

O precompiler identifica instruções SQL e prepara os elementos necessários para o processamento posterior.

Esse fluxo explica por que desenvolvimento COBOL + Db2 envolve muito mais que:

compilar
executar

25. DBRM e PACKAGE — o que Spock realmente queria encontrar

O DBRM guarda informações extraídas das instruções SQL durante a preparação.

Posteriormente ocorre o BIND.

O BIND gera estruturas como packages utilizadas pela execução.

Simplificando:

SQL
 ↓
DBRM
 ↓
BIND
 ↓
PACKAGE
 ↓
Access Path

O package é extremamente importante.

Porque o programa COBOL pode continuar exatamente igual enquanto o comportamento do SQL muda por razões relacionadas a:

  • rebind;

  • novas estatísticas;

  • novos índices;

  • alteração do ambiente;

  • manutenção;

  • mudança de release;

  • access path diferente.

Essa é uma das primeiras grandes revelações para quem trabalha com performance.

Código-fonte igual não significa necessariamente comportamento operacional idêntico.


26. BIND — o casamento arranjado entre SQL e Db2

O BIND é uma etapa fundamental da vida do SQL estático.

É quando informações do DBRM são utilizadas para produzir um package.

E ali são tomadas decisões importantíssimas.

Se você aprende apenas a programar:

EXEC SQL ...

mas não aprende:

  • package;

  • bind;

  • rebind;

  • access path;

você aprendeu a dirigir, mas nunca abriu o capô.

Serve.

Até o carro começar a fazer barulho.


27. O verdadeiro caminho de um SELECT

Nosso jovem programador agora olha novamente para:

SELECT SALDO
FROM CONTA
WHERE NUM_CONTA = :WS-CONTA;

Mas depois da aula de Spock ele já enxerga outra coisa:

COBOL
  ↓
CICS
  ↓
Thread Db2
  ↓
Package
  ↓
Access Path
  ↓
Index?
  ↓
Buffer Pool
  ↓
Página disponível?
   ├── SIM → usa memória
   └── NÃO → solicita I/O
                  ↓
                Storage
                  ↓
              Buffer Pool
                  ↓
                 Db2
                  ↓
                COBOL

Aquela linha de SQL agora parece uma missão espacial inteira.

E é exatamente essa mudança de percepção que diferencia alguém que apenas escreve SQL de alguém que começa a compreender o Db2.


28. DFSMS — quando descobrimos que storage também faz parte do banco

Db2 não administra storage em um vácuo.

No z/OS existe integração com o universo do DFSMS — Data Facility Storage Management Subsystem.

Entram conceitos como:

  • datasets;

  • volumes;

  • storage classes;

  • management classes;

  • data classes;

  • políticas SMS;

  • VSAM.

Esse ponto é profundamente “mainframe”.

Em plataformas mais simples, desenvolvedor e banco às vezes parecem universos separados do storage.

No z/OS, você começa a perceber que:

banco
+
storage
+
sistema operacional
+
segurança
+
workload management

formam uma arquitetura integrada.


29. E então aparece VSAM escondido atrás da cortina

Essa curiosidade normalmente surpreende o iniciante.

Db2 for z/OS utiliza infraestrutura de armazenamento associada ao ecossistema VSAM para seus datasets.

Então podemos desenhar:

Db2 object
   ↓
Table Space
   ↓
datasets
   ↓
VSAM / DFSMS
   ↓
storage

Mas atenção:

Isso NÃO significa que Db2 seja simplesmente “um VSAM com SQL”.

Db2 acrescenta um universo inteiro:

  • modelo relacional;

  • SQL;

  • optimizer;

  • locking;

  • logging;

  • recovery;

  • catálogo;

  • integridade;

  • transações.

VSAM e Db2 possuem propósitos e abstrações diferentes.


30. RACF — nem Spock acessa folha de pagamento sem autorização

Agora imagine:

SELECT *
FROM FOLHA_PAGAMENTO;

Tecnicamente válido.

Mas deveria qualquer programa poder executá-lo?

Claro que não.

Entram mecanismos de segurança do ambiente, incluindo integração com RACF e os mecanismos de autorização do próprio Db2.

A regra fundamental:

SQL válido
≠
SQL autorizado

E ainda bem.

Imagine um estagiário descobrindo:

SELECT *
FROM SALARIOS_DIRETORIA;

e dizendo:

— Funcionou no desenvolvimento.

Produção:

ICH408I

O RACF entra em cena como o segurança vulcano:

— Seu entusiasmo não constitui autorização.


31. WLM — todos são iguais, mas alguns workloads precisam responder em 100 milissegundos

Outro componente importante do ecossistema é o WLM — Workload Manager.

O z/OS pode administrar workloads conforme objetivos definidos.

Imagine simultaneamente:

Transação PIX
Consulta de saldo
Batch de faturamento
Relatório gerencial
Backup
Compilação
Job de teste

Todos querem CPU.

Todos acham que são importantes.

Alguns realmente são.

WLM ajuda o sistema a priorizar recursos conforme políticas de serviço.

Pense nele como o oficial de operações da ponte:

“Essa transação é crítica.”
“Esse relatório pode esperar.”
“Esse batch precisa terminar antes das 06:00.”

É uma das grandes razões pelas quais mainframes conseguem misturar workloads muito distintos de forma eficiente.


32. MQ, CICS, TCP/IP e companhia — Db2 nunca esteve sozinho

Observe uma arquitetura corporativa típica:

Mobile
  ↓
API
  ↓
z/OS Connect
  ↓
CICS
  ↓
COBOL
  ↓
Db2

Ao lado:

COBOL
  ↓
MQ
  ↓
sistema externo

Com:

RACF → segurança
WLM  → prioridades
DFSMS → storage
TCP/IP → comunicação
JES → batch

O segredo do mainframe nunca foi um único produto.

É a integração.

Isso vale para Db2 também.


33. Parallel Sysplex — quando uma Enterprise deixa de ser suficiente

Agora entramos em território mais avançado.

Em ambientes de altíssima disponibilidade, Db2 pode operar em configuração de Data Sharing, dentro do universo do Parallel Sysplex.

Imagine:

            Aplicações
                │
      ┌─────────┼─────────┐
      ↓         ↓         ↓
    DB2A      DB2B      DB2C
      │         │         │
      └─────────┼─────────┘
                ↓
      dados compartilhados

Vários membros Db2 podem trabalhar cooperativamente.

Isso proporciona benefícios associados a:

  • disponibilidade;

  • escalabilidade;

  • flexibilidade operacional;

  • continuidade.

Mas surge um problema lógico.

Se DB2A e DB2B acessam os mesmos dados:

Como garantir coerência?

Excelente pergunta, jovem cadete.


34. Coupling Facility e Group Buffer Pool

No Data Sharing entram estruturas disponibilizadas através da Coupling Facility.

Entre elas aparecem mecanismos relacionados a Group Buffer Pools e coordenação entre membros.

Simplificando:

DB2A                     DB2B
 │                         │
Buffer Pool            Buffer Pool
 │                         │
 └──────────┐   ┌──────────┘
            ↓   ↓
      Coupling Facility
            │
      Group Buffer Pool

Se vários membros acessam os mesmos dados, precisamos impedir que cada um viva numa realidade alternativa.

Afinal, nem Star Trek resolve consistência eventual com universo paralelo em folha de pagamento.


35. O programa funciona, mas está lento. E agora?

Este é um dos momentos mais importantes da carreira.

Iniciante:

“O SQL está lento.”

Profissional experiente:

“Vamos descobrir por quê.”

Possibilidades:

SQL ruim
estatísticas inadequadas
índice ausente
índice inadequado
access path diferente
muito I/O
Buffer Pool pressionado
contenção
locks
volume de dados cresceu
commit inadequado
CPU
storage
DDF
rede
WLM

Percebe a diferença?

Performance não é adivinhação.

É investigação.

Mr. Spock aprovaria.


36. Checklist Bellacosa para o COBOL iniciante

Quando um SQL apresentar problema, pergunte nesta ordem aproximada:

  1. O SQL está logicamente correto?

  2. Quantas linhas deveriam retornar?

  3. Quantas realmente retornam?

  4. Existe índice apropriado?

  5. Qual access path está sendo usado?

  6. As estatísticas estão atualizadas?

  7. Houve REBIND recentemente?

  8. O volume de dados mudou?

  9. Existe contenção?

  10. Existe timeout ou deadlock?

  11. O programa está dando commits adequadamente?

  12. O problema acontece sempre ou apenas em horários específicos?

  13. É batch, CICS ou acesso distribuído?

  14. Existe pressão de CPU ou I/O?

  15. Houve mudança no ambiente?

Já percebeu que:

“Está lento porque Db2 está lento”

é praticamente uma não-explicação.


37. O easter egg do SQLCODE

Todo programador COBOL conhece algum momento assim:

IF SQLCODE NOT = 0
    DISPLAY 'ERRO DB2'
END-IF

Spock vê isso.

Fica silencioso durante oito segundos.

Depois diz:

— Fascinante. Você descartou todas as informações diagnósticas e preservou apenas o fato de que algo ocorreu.

Não seja esse programador.

SQLCODE é começo de diagnóstico.

Não fim.

Considere também as informações disponibilizadas por SQLCA e mecanismos apropriados de diagnóstico.

A mensagem:

ERRO DB2

é quase equivalente a chamar a manutenção dizendo:

“A máquina não está normal.”

Boa sorte.


38. Segundo easter egg: SELECT *

Spock observa:

SELECT *
FROM CLIENTE;

— Por que você deseja todas as colunas?

— Porque é mais fácil.

— Essa justificativa não parece relacionada à necessidade funcional.

Silêncio.

SELECT * pode ser conveniente em testes.

Em aplicação profissional, pense nas colunas realmente necessárias.

Isso melhora:

  • clareza;

  • manutenção;

  • previsibilidade;

  • potencialmente movimentação de dados;

  • dependências.

Escreva o que precisa.

Não o que seus dedos acharam mais curto.


39. Terceiro easter egg: COMMIT dentro do loop sem pensar

Outro clássico:

PERFORM UNTIL EOF
   ...
   EXEC SQL
      UPDATE ...
   END-EXEC

   EXEC SQL
      COMMIT
   END-EXEC
END-PERFORM

Talvez seja correto.

Talvez seja horrível.

Depende.

A pergunta certa não é:

“Posso dar COMMIT aqui?”

É:

“Qual unidade de trabalho faz sentido para esse processo?”

Em batch, estratégia de commit precisa considerar:

  • restart;

  • volume;

  • locking;

  • recuperação;

  • consistência;

  • desempenho.


40. A diferença entre saber SQL e saber Db2

Este talvez seja o ponto mais importante do artigo.

Conhecer:

SELECT
INSERT
UPDATE
DELETE
JOIN
GROUP BY

é conhecer SQL.

Essencial.

Mas conhecer Db2 for z/OS envolve também:

Subsystem
DBM1
MSTR
IRLM
DDF
Buffer Pool
EDM Pool
Table Space
Index Space
Catalog
Directory
Package
DBRM
BIND
Access Path
RUNSTATS
Logs
Recovery
Image Copy
DFSMS
RACF
WLM
Data Sharing
Parallel Sysplex

É outro nível de entendimento.

E você não precisa aprender tudo no primeiro mês.

Apenas precisa saber que essas camadas existem.


41. Um caminho de estudo em sete missões

Se eu estivesse orientando um programador COBOL iniciante, faria assim.

Missão 1 — SQL

Aprenda bem:

SELECT
INSERT
UPDATE
DELETE
JOIN
CURSOR
NULL
SQLCODE

Missão 2 — COBOL + Db2

Entenda:

host variables
SQLCA
cursor
commit
rollback

Missão 3 — preparação

Estude:

Precompile
DBRM
Bind
Package
Plan

Missão 4 — armazenamento

Estude:

Table Space
Index
Page
Buffer Pool

Missão 5 — optimizer

Estude:

Access Path
RUNSTATS
EXPLAIN
seletividade
cardinalidade

Missão 6 — concorrência

Estude:

Lock
Timeout
Deadlock
Isolation
Commit

Missão 7 — arquitetura z/OS

Finalmente:

IRLM
DDF
DFSMS
RACF
WLM
Logs
Recovery
Data Sharing

Quando terminar isso, volte à Missão 1.

Você descobrirá que seu antigo SELECT mudou completamente.


42. A grande revelação

Nosso programador volta finalmente ao código:

EXEC SQL
   SELECT NOME,
          SALDO
     INTO :WS-NOME,
          :WS-SALDO
     FROM CLIENTE
    WHERE CONTA = :WS-CONTA
END-EXEC.

Antes ele via:

“Busca o saldo.”

Agora enxerga:

Aplicação
 ↓
contexto Db2
 ↓
Package
 ↓
Access Path
 ↓
Optimizer
 ↓
Statistics
 ↓
Index
 ↓
Buffer Pool
 ↓
Page
 ↓
possível I/O
 ↓
Storage
 ↓
controle transacional
 ↓
segurança
 ↓
resultado

Ele olha para Spock.

— Então nunca foi “só um SELECT”.

Spock responde:

— Correto.

— E tudo isso acontece para devolver duas colunas?

— Correto.

— Isso é completamente insano.

Spock levanta novamente a sobrancelha.

— Eu escolheria a palavra “engenharia”.


Epílogo — Vida longa ao Db2

Existe uma tendência natural de ensinar mainframe de fora para dentro.

Primeiro mostramos:

IDENTIFICATION DIVISION.

Depois:

EXEC SQL.

Depois CICS.

Depois JCL.

Está correto.

O problema é quando o aprendizado para ali.

Um profissional começa realmente a amadurecer quando pergunta:

O que existe atrás dessa instrução?

Db2 é um ótimo exemplo.

Por trás do humilde:

SELECT SALDO

existe uma arquitetura desenhada para funcionar em ambientes nos quais:

  • milhões de transações podem acontecer;

  • múltiplas aplicações disputam recursos;

  • dados precisam permanecer consistentes;

  • falhas precisam ser recuperáveis;

  • workloads críticos têm prioridade;

  • segurança precisa ser auditável;

  • sistemas externos precisam acessar dados;

  • operações precisam continuar durante enormes cargas.

É por isso que Db2 for z/OS não deve ser estudado apenas como linguagem SQL.

Ele deve ser entendido como parte de uma arquitetura transacional completa.

Buffer Pool ensina que memória é estratégia.

IRLM ensina que concorrência precisa de disciplina.

RUNSTATS ensina que inteligência depende de boas informações.

Logs ensinam que sobreviver ao desastre é tão importante quanto evitar o desastre.

RACF ensina que capacidade técnica não significa autorização.

WLM ensina que nem todo trabalho possui a mesma urgência.

DDF ensina que mainframe não é uma ilha.

Parallel Sysplex ensina que alta disponibilidade é uma arquitetura, não uma frase de marketing.

E o humble COBOL programador aprende finalmente uma verdade que acompanha muita gente durante décadas de carreira:

quanto mais você entende o que existe abaixo do seu programa, melhores ficam as decisões que você toma acima dele.

Spock deixou o CPD pouco antes das três da manhã.

Na saída, encontrou o operador.

— O senhor está indo embora?

— Acredito que meu trabalho aqui terminou.

— E o garoto?

Spock olhou através do vidro para o programador, que naquele momento pesquisava access path, Buffer Pool e RUNSTATS enquanto sua caneca de café esfriava ao lado do terminal.

— Ele cometeu um erro comum.

— Qual?

— Pensou que estava aprendendo apenas COBOL.

Spock fez uma pequena pausa.

— Agora começou a aprender sistemas.

O elevador fechou.

No monitor apareceu:

DSN SYSTEM(...)

Depois:

READY

E em algum lugar profundamente dentro do z/OS, um Buffer Pool continuou recebendo páginas, o IRLM continuou arbitrando recursos, os logs continuaram registrando transações e o velho Db2 fez aquilo que vem fazendo há décadas:

carregar boa parte do mundo corporativo nas costas sem exigir que o usuário saiba quantas maravilhas estavam acontecendo atrás de um simples SELECT.

🖖 Vida longa, prosperidade e um access path decente.

terça-feira, 8 de fevereiro de 2022

🧪 PROFESSOR FARNSWORTH E AS QUATRO LEIS QUE IMPEDIAM O Db2 DE DESTRUIR O UNIVERSO

 

Bellacosa Mainframe apresenta o ACID

☕ Um Café no Bellacosa Mainframe

🧪 PROFESSOR FARNSWORTH E AS QUATRO LEIS QUE IMPEDIAM O Db2 DE DESTRUIR O UNIVERSO

ACID, COBOL, Db2 for z/OS, COMMIT, ROLLBACK, Unit of Work, locks, IRLM, isolation levels, buffer pools, logging, recovery, CICS, deadlocks, restart — e o dia em que o Professor Farnsworth descobriu que “Good news, everyone!” não era uma estratégia válida de recuperação de banco de dados.

Sob a tutela do Professor Hubert J. Farnsworth, da Planet Express.



🎬 PRÓLOGO — BOAS NOTÍCIAS, PESSOAL!

Eram exatamente 03:17 da manhã quando o telefone tocou.

Nenhum programador COBOL experiente gosta de um telefone tocando às 03:17.

Às 08:00, telefone significa reunião.

Às 14:00, provavelmente alguém esqueceu uma vírgula no JCL.

Às 17:30, significa mudança emergencial que alguém garante ter sido "exaustivamente testada".

Mas às 03:17?

Às 03:17 significa produção.

O jovem programador levantou da cama, abriu o notebook e encontrou uma mensagem assustadora:

URGENTE

TRANSFERÊNCIA FINANCEIRA INCONSISTENTE

CONTA A = DEBITADA
CONTA B = NÃO CREDITADA

— Professor! Temos um problema!

Do fundo do laboratório surgiu uma figura de jaleco, chinelos e óculos grossos.

Professor Hubert J. Farnsworth levantou um dedo.

— Good news, everyone!

— Professor, desapareceram mil reais.

— Então talvez as notícias não sejam tão boas.

Na tela havia algo parecido com isto:

EXEC SQL
   UPDATE CONTA
      SET SALDO = SALDO - 1000
    WHERE CONTA_ID = 100
END-EXEC.

EXEC SQL
   UPDATE CONTA
      SET SALDO = SALDO + 1000
    WHERE CONTA_ID = 200
END-EXEC.

EXEC SQL
   COMMIT
END-EXEC.

O jovem programador olhou para o código.

— Parece simples.

Farnsworth sorriu.

Esse era precisamente o problema.

Porque atrás daquele pequeno COMMIT existia um universo inteiro chamado:

ACID.



🧪 CAPÍTULO 1 — AS QUATRO LEIS DO UNIVERSO TRANSACIONAL

Quem começa a estudar banco de dados encontra rapidamente a famosa sigla:

A — Atomicity
C — Consistency
I — Isolation
D — Durability

Em português:

Atomicidade
Consistência
Isolamento
Durabilidade

O resumo de bolso é:

Atomicidade  → tudo ou nada
Consistência → dados continuam válidos
Isolamento   → controlar concorrência
Durabilidade → confirmou, deve permanecer

Está correto.

Mas para quem trabalha com Db2 for z/OS, isso é apenas a porta do laboratório.

Atrás dela encontramos:

COBOL
   │
   ▼
CICS / Batch
   │
   ▼
Db2
   │
   ├── Unit of Work
   ├── COMMIT / ROLLBACK
   ├── Locks
   ├── IRLM
   ├── Isolation Levels
   ├── Buffer Pools
   ├── Logging
   ├── Checkpoints
   ├── Recovery
   └── Restart

ACID não é simplesmente uma propriedade acadêmica do banco.

É uma resposta para uma pergunta muito mais séria:

Como manter os dados confiáveis quando programas falham, máquinas param, transações concorrem e seres humanos fazem coisas que o Professor Farnsworth jamais colocaria em uma especificação?

Vamos entrar no laboratório.



⚛️ CAPÍTULO 2 — A DE ATOMICITY: NÃO EXISTE MEIA TRANSFERÊNCIA

Imagine duas contas:

CONTA A = R$ 5.000
CONTA B = R$ 3.000

Precisamos transferir:

R$ 1.000

O resultado correto é:

CONTA A = R$ 4.000
CONTA B = R$ 4.000

O programa executa:

1. debita A
2. credita B
3. registra movimento
4. COMMIT

Mas o universo não é obrigado a colaborar.

Pode acontecer:

1. debita A ............ OK
2. credita B ........... OK
3. registra movimento .. ABEND

Sem atomicidade, poderíamos terminar com um estado parcialmente processado.

E isso é exatamente o que não queremos.

Farnsworth desenharia no quadro:

          UNIT OF WORK
┌───────────────────────────────┐
│ UPDATE CONTA A               │
│ UPDATE CONTA B               │
│ INSERT MOVIMENTO             │
│                              │
│ COMMIT                       │
└───────────────────────────────┘

Essa caixa representa uma Unit of Work, ou UOW.

Ela é muito mais importante do que pensar individualmente em cada SQL.

O iniciante olha para:

UPDATE CONTA ...

O engenheiro começa a perguntar:

A qual unidade lógica de negócio esse UPDATE pertence?

Essa mudança mental é enorme.



💥 CAPÍTULO 3 — O ABEND NO MEIO DA EXPERIÊNCIA

Agora Farnsworth puxa uma enorme alavanca vermelha.

O jovem programador grita:

— Professor, o que essa alavanca faz?

CLICK.

As luzes apagam.

— Descobriremos!

Imagine que o Db2 estivesse processando:

BEGIN UOW

UPDATE A
     │
     ▼
A = 4000

UPDATE B
     │
     ▼

💥 FALHA

A transação ainda não chegou ao seu ponto de confirmação.

O banco precisa conseguir impedir que o trabalho incompleto se transforme permanentemente no novo estado lógico.

É aí que entram mecanismos como:

ROLLBACK
BACKOUT
LOGGING
RECOVERY

A ideia de atomicidade pode ser resumida assim:

             TRANSAÇÃO

                  │
          ┌───────┴───────┐
          ▼               ▼
       SUCESSO           FALHA
          │               │
          ▼               ▼
       COMMIT        ROLLBACK/BACKOUT
          │               │
          ▼               ▼
     CONFIRMADA       DESFEITA

O importante é que o banco não termine no meio do caminho lógico.



🛑 CAPÍTULO 4 — COMMIT NÃO SIGNIFICA APENAS "SALVAR"

Essa é uma das primeiras armadilhas para o programador COBOL iniciante.

Muitos aprendem:

COMMIT   = salvar
ROLLBACK = desfazer

Não está totalmente errado.

Mas é uma simplificação perigosa.

Pense no COMMIT como:

a declaração de que uma Unit of Work alcançou seu ponto de confirmação.

Portanto:

EXEC SQL
   COMMIT
END-EXEC.

não deveria ser colocado aleatoriamente no programa.

O lugar do COMMIT define fronteiras transacionais.

Imagine um batch processando dez milhões de registros.

Você poderia fazer:

registro 1
registro 2
registro 3
...
registro 10.000.000

COMMIT

Farnsworth olharia para isso e provavelmente diria:

— Excelente! Agora só precisamos esperar alguma coisa falhar no registro 9.999.999.

Uma UOW gigantesca pode trazer consequências para logging, recursos, locking, rollback, concorrência e restart.

Por isso aplicações batch frequentemente utilizam commits periódicos:

processa 1.000
COMMIT

processa 1.000
COMMIT

processa 1.000
COMMIT

Mas atenção.

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

COMMIT A CADA 1000

que seja correto para todas as aplicações.

O intervalo depende de coisas como volume, duração, concorrência, requisitos do negócio, custo de restart e características do workload.


🔄 CAPÍTULO 5 — DEPOIS DO COMMIT NÃO EXISTE BORRACHA MÁGICA

Suponha:

Registros 1–1000
COMMIT

1001–2000
COMMIT

2001–3000
COMMIT

3001–3782
💥 ABEND

Um ROLLBACK não vai magicamente voltar ao registro 1.

As UOWs anteriores já foram confirmadas.

O programa precisa saber:

último COMMIT válido = registro 3000

E isso nos leva a um conceito importantíssimo em batch:

Restartability.

Uma aplicação bem projetada pode guardar um checkpoint lógico próprio, chave de último registro processado ou outra informação de controle adequada ao desenho.

No restart:

JOB reiniciado
      │
      ▼
consulta controle
      │
      ▼
último ponto = 3000
      │
      ▼
continua de forma segura

E surge uma nova pergunta:

Se eu executar novamente uma operação, ela produzirá o mesmo resultado ou duplicará dinheiro?

Bem-vindo ao mundo da idempotência.

ACID não resolve sozinho todos os problemas de restart da aplicação.


🧱 CAPÍTULO 6 — C DE CONSISTENCY: O Db2 NÃO CONHECE O REGULAMENTO DO PLANETA EXPRESS

Consistência significa que uma transação deve levar o banco de um estado válido para outro estado válido, respeitando as regras relevantes.

O Db2 conhece muitas regras estruturais porque nós as declaramos.

Por exemplo:

CREATE TABLE CONTA
(
    CONTA_ID INTEGER NOT NULL,
    CLIENTE_ID INTEGER NOT NULL,
    SALDO DECIMAL(15,2) NOT NULL,

    PRIMARY KEY (CONTA_ID)
);

Podemos utilizar mecanismos como:

PRIMARY KEY
FOREIGN KEY
UNIQUE
CHECK
NOT NULL

Eles ajudam a preservar integridade.

Por exemplo, uma FOREIGN KEY pode estabelecer uma relação entre conta e cliente.

Mas Farnsworth faz uma pergunta:

— O Db2 sabe que clientes marcianos recebem 15% de desconto às terças-feiras?

Não.

A menos que essa regra esteja adequadamente representada na solução, o banco não a inventará.

Temos então três mundos:

       CONSISTÊNCIA

      /      |       \
     /       |        \
    ▼        ▼         ▼

DATABASE   APLICAÇÃO   NEGÓCIO

Um valor pode ser perfeitamente válido para um DECIMAL(15,2) e completamente absurdo para a empresa.

Por exemplo:

SALDO = -999999999.99

O datatype pode aceitar.

A regra empresarial talvez não.

Portanto:

Consistência ACID não significa que o Db2 entende automaticamente todas as regras da empresa.

Essa é uma diferença pequena na frase e gigantesca na arquitetura.


👥 CAPÍTULO 7 — I DE ISOLATION: FRY E BENDER SACAM O MESMO DINHEIRO

Agora temos:

SALDO = R$ 1.000

Fry tenta sacar:

R$ 800

Bender, exatamente ao mesmo tempo, tenta sacar:

R$ 800

Imagine ingenuamente:

FRY                       BENDER

SELECT SALDO              SELECT SALDO
     │                         │
     ▼                         ▼
   1000                      1000

"Tem dinheiro!"            "Tem dinheiro!"

Agora os dois tentam continuar.

Concorrência é um dos grandes problemas que bancos de dados transacionais precisam controlar.

É aqui que Isolation começa a conversar com:

locks
IRLM
UR
CS
RS
RR
deadlocks
timeouts

🔐 CAPÍTULO 8 — IRLM: O PORTEIRO DO LABORATÓRIO

No ecossistema Db2 for z/OS aparece um personagem importantíssimo:

IRLM — Internal Resource Lock Manager.

Uma representação conceitual:

PROGRAMA A
    │
    ▼
   Db2
    │
    ▼
   IRLM
    ▲
    │
PROGRAMA B

Suponha que A esteja alterando determinado recurso e possua um lock incompatível com aquilo que B deseja fazer.

B pode precisar esperar.

A:

UPDATE CONTA 100
      │
      ▼
    LOCK
      │
      │
      │     B:
      │
      │     UPDATE CONTA 100
      │            │
      │            ▼
      │           WAIT
      │
   COMMIT
      │
      ▼
 liberação conforme
 regras aplicáveis

O usuário pode reclamar:

"O sistema está esperando!"

Mas aquela espera pode ser justamente parte do mecanismo que evita resultados transacionais incorretos.

Performance e consistência frequentemente precisam conversar.


👻 CAPÍTULO 9 — O FANTASMA DO DIRTY READ

Farnsworth altera um saldo:

T1:

1000 → 100

Mas ainda não fez COMMIT.

Outra transação lê aquele valor.

Depois T1 executa:

ROLLBACK

O saldo retorna a 1000.

A segunda transação acabou de enxergar um valor que nunca se tornou um estado confirmado.

Esse fenômeno é associado a:

Dirty Read.

Conceitualmente:

T1                T2

UPDATE 100
   │
   │
   ├──────────► lê 100
   │
ROLLBACK
   │
   ▼
volta 1000

T2 tomou conhecimento de um estado intermediário que foi posteriormente abandonado.

E agora precisamos falar dos níveis de isolamento.


🧬 CAPÍTULO 10 — UR, CS, RS E RR

No Db2 for z/OS, quatro nomes aparecem frequentemente:

UR — Uncommitted Read
CS — Cursor Stability
RS — Read Stability
RR — Repeatable Read

O erro do iniciante é imaginar:

UR = ruim
RR = excelente

Não.

São escolhas com comportamentos e custos diferentes.

Uma maneira didática de pensar é:

            maior proteção
                  ▲
                  │
                 RR
                  │
                 RS
                  │
                 CS
                  │
                 UR
                  │
                  ▼
       maior liberdade de leitura

Mas não transforme isso numa simples régua de qualidade.

A pergunta correta é:

Qual garantia de isolamento esta transação realmente precisa?

Um relatório estatístico pode aceitar comportamento que seria inadmissível em uma autorização financeira.

Mais isolamento também pode significar impactos na concorrência e no locking.

Engenharia é escolher conscientemente.


👻 CAPÍTULO 11 — NON-REPEATABLE READ

Fry executa:

SELECT SALDO
FROM CONTA
WHERE CONTA_ID = 10;

Obtém:

1000

Outra transação altera a mesma linha e confirma:

1000 → 1500

COMMIT

Fry lê novamente e, dependendo das garantias aplicáveis, pode encontrar:

1500

Temos conceitualmente:

primeira leitura = 1000

segunda leitura  = 1500

A mesma linha não repetiu o valor observado anteriormente.

Daí o nome:

non-repeatable read.


👻 CAPÍTULO 12 — PHANTOM READ: AGORA APARECEU OUTRO BENDER

Considere:

SELECT COUNT(*)
FROM PEDIDO
WHERE STATUS = 'PENDENTE';

Resultado:

100

Outra transação executa:

INSERT INTO PEDIDO ...

criando outro pedido PENDENTE, e confirma.

Uma nova execução da consulta pode encontrar:

101

A diferença para o exemplo anterior é fascinante.

Não necessariamente alteraram uma das linhas que você já tinha visto.

O conjunto de linhas que satisfaz o predicado mudou.

Temos então três fenômenos fáceis de diferenciar:

DIRTY READ
→ observei dado não confirmado.

NON-REPEATABLE READ
→ uma linha observada mudou.

PHANTOM
→ o conjunto correspondente ao predicado mudou.

Farnsworth chamaria o último de:

— Fantasmas quânticos relacionais!

Não use esse termo numa prova de certificação.


💀 CAPÍTULO 13 — DEADLOCK: FRY ESPERA BENDER, BENDER ESPERA FRY

Imagine:

TRANSAÇÃO A                TRANSAÇÃO B

LOCK RECURSO X             LOCK RECURSO Y
      │                          │
      ▼                          ▼

quer Y                      quer X
      │                          │
      ▼                          ▼

WAIT                         WAIT

Temos um ciclo:

A espera B
▲         │
│         ▼
└──────── B

Isso é deadlock.

O sistema precisa romper a situação e uma das unidades de trabalho envolvidas acaba sendo tratada como vítima.

Para o programador COBOL surge uma lição essencial:

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

não representa tratamento transacional adequado.

É necessário compreender o SQLCODE/SQLSTATE e decidir o comportamento correto da aplicação.


⏱️ CAPÍTULO 14 — TIMEOUT NÃO É DEADLOCK

Farnsworth deixa Bender segurando a chave do laboratório.

Fry espera.

E espera.

E espera.

Não existe necessariamente um ciclo.

Existe um recurso indisponível durante tempo suficiente para que o limite aplicável seja atingido.

Conceitualmente:

DEADLOCK:

A → B
↑   │
└───┘


TIMEOUT:

A possui recurso

B → WAIT → WAIT → WAIT → limite

Para o usuário:

"Travou."

Para quem investiga produção:

Precisamos saber exatamente por quê.

Essa é a diferença entre observar sintoma e diagnosticar sistema.


💾 CAPÍTULO 15 — D DE DURABILITY: O SEGREDO DO COMMIT

Agora Farnsworth aperta novamente o botão vermelho.

— Professor, não!

Tarde demais.

💥

O Db2 caiu logo depois de uma transação ter sido confirmada.

A pergunta é:

Os dados confirmados desapareceram?

A durabilidade existe justamente para estabelecer a expectativa de que uma transação efetivamente comprometida sobreviva a falhas dentro das garantias do sistema.

Mas aqui encontramos uma curiosidade fantástica.

Muitos iniciantes imaginam:

UPDATE
   │
   ▼
grava imediatamente a página no DASD
   │
   ▼
COMMIT

Essa visão é simples demais.

Db2 utiliza buffer pools.


🏊 CAPÍTULO 16 — BUFFER POOL: A PISCINA DO PROFESSOR

Imagine uma página trazida para memória:

       DASD
         │
         ▼
    BUFFER POOL
   ┌────────────┐
   │ DATA PAGE  │
   └────────────┘

Ela é alterada:

    BUFFER POOL
   ┌────────────┐
   │ MODIFIED   │
   │   PAGE     │
   └────────────┘

Essa página modificada precisa, em algum momento apropriado, chegar ao armazenamento persistente.

Mas seria terrivelmente caro exigir ingenuamente uma escrita física completa da página de dados a cada simples UPDATE.

Então surge outro personagem fundamental:

O Db2 Log.


📜 CAPÍTULO 17 — O DIÁRIO SECRETO DO Db2

O Db2 mantém informações de log essenciais para recovery.

Mentalmente:

             SQL UPDATE
                 │
        ┌────────┴────────┐
        ▼                 ▼
   BUFFER POOL          LOG
        │                 │
        ▼                 ▼
   DATA PAGES         RECOVERY

É por isso que uma ideia crucial é:

COMMIT não deve ser entendido como "todas as páginas modificadas foram necessariamente gravadas fisicamente no tablespace naquele mesmo instante".

O sistema possui mecanismos de logging e recuperação justamente para separar adequadamente esses eventos sem abandonar durabilidade.

Esse ponto muda completamente a compreensão do COMMIT.


✍️ CAPÍTULO 18 — WRITE-AHEAD LOGGING

Entra em cena o princípio de Write-Ahead Logging, WAL.

De forma didática, as informações de log necessárias à recuperação precisam obedecer à ordenação apropriada em relação às páginas de dados modificadas.

Farnsworth explicaria:

Antes de mandar Bender alterar o universo, anote no diário o suficiente para descobrir depois o que ele fez.

Suponha o log conceitual:

T001 UPDATE A
T001 UPDATE B
T001 COMMIT

T002 UPDATE C
T002 UPDATE D

💥 CRASH

Temos duas situações.

T001 foi confirmada.

T002 não chegou ao commit.

Durante recovery, o sistema possui informações para preservar/reaplicar o que deve sobreviver e desfazer/backout do que não deveria permanecer, conforme necessário.

Didaticamente:

T001 → REDO se necessário

T002 → UNDO/BACKOUT conforme necessário

E aqui acontece algo maravilhoso.


♻️ CAPÍTULO 19 — ATOMICITY E DURABILITY SE ENCONTRAM NO LOG

Veja:

                    LOG
                  /     \
                 /       \
                ▼         ▼
              UNDO       REDO
                │         │
                ▼         ▼
          ATOMICITY   DURABILITY

Atomicidade diz:

Trabalho incompleto não pode permanecer como se estivesse confirmado.

Durabilidade diz:

Trabalho confirmado não deve desaparecer simplesmente porque houve uma falha.

O log ajuda o Db2 a navegar entre esses dois mundos.

ACID deixa de parecer quatro palavras independentes.

É uma engrenagem.


🗄️ CAPÍTULO 20 — ACTIVE LOG, ARCHIVE LOG E A MÁQUINA DO TEMPO

No Db2 for z/OS encontramos active logs e archive logs dentro da arquitetura de logging.

Uma representação simplificada:

TRANSAÇÕES
     │
     ▼
 ACTIVE LOG
     │
     │ offload
     ▼
ARCHIVE LOG

Ao avançarmos em Db2 recovery aparecem ainda termos importantíssimos:

BSDS
RBA / LRSN
checkpoints
image copies
RECOVER
restart
active logs
archive logs

Perceba como uma simples aula sobre ACID acaba levando diretamente para Backup & Recovery de Db2 for z/OS.

É por isso que conhecimento mainframe funciona como uma catedral.

Você abre uma porta e encontra outras vinte.


🚦 CAPÍTULO 21 — COMMIT, CHECKPOINT E IMAGE COPY NÃO SÃO A MESMA COISA

Guarde isto:

COMMIT ≠ CHECKPOINT ≠ IMAGE COPY

O COMMIT está relacionado à confirmação da Unit of Work.

O checkpoint do Db2 participa de mecanismos internos importantes para restart/recovery e gerenciamento do sistema.

Uma image copy é utilizada dentro da estratégia de backup/recovery dos objetos Db2.

Três ferramentas do universo da confiabilidade.

Três finalidades diferentes.

Misturá-las é como confundir:

SAVE
BACKUP
TRANSACTION

só porque todas parecem envolver a ideia de "não perder alguma coisa".


🚀 CAPÍTULO 22 — PROFESSOR, TEM CICS NESSA EXPERIÊNCIA?

Tem.

E agora Farnsworth realmente fica animado.

Imagine:

ATM / MOBILE / API
        │
        ▼
       CICS
        │
        ▼
      COBOL
        │
   ┌────┼────┐
   ▼    ▼    ▼
  Db2   MQ   VSAM

Uma única operação de negócio pode envolver vários recursos.

Suponha:

1. atualizar Db2
2. atualizar outro recurso transacional
3. produzir uma mensagem

A pergunta já não é apenas:

O Db2 confirmou?

Passa a ser:

A unidade lógica completa foi coordenada corretamente entre os resource managers participantes?

Aqui aparecem conceitos como:

SYNCPOINT
resource managers
transaction coordination
two-phase commit

E percebemos por que o mundo transacional mainframe é muito maior que EXEC SQL.


🤝 CAPÍTULO 23 — TWO-PHASE COMMIT, OU "TODO MUNDO PRONTO?"

Didaticamente, pense num coordenador perguntando:

              COORDENADOR
                   │
          ┌────────┴────────┐
          ▼                 ▼
         Db2                MQ

       pronto?            pronto?
          │                 │
         YES               YES
          │                 │
          └────────┬────────┘
                   ▼
                 COMMIT

Se a operação não puder prosseguir adequadamente, entra o caminho de rollback/recovery previsto pelo protocolo e pelos participantes.

A realidade é mais sofisticada que esse desenho, mas ele mostra uma coisa essencial:

Atomicidade dentro de um banco já é interessante. Atomicidade envolvendo múltiplos resource managers é outro nível de engenharia.


📦 CAPÍTULO 24 — ACID NÃO IMPEDE PAGAMENTO DUPLICADO POR MÁGICA

Farnsworth envia a mensagem:

PAGAMENTO 98472

A rede apresenta problema.

A aplicação tenta novamente:

PAGAMENTO 98472

Temos duas mensagens.

Cada processamento individual pode ser perfeitamente ACID.

Ainda assim, se a aplicação não identificar a duplicidade, poderemos processar o mesmo evento duas vezes.

Talvez o desenho utilize algo equivalente a:

TRANSACTION_ID UNIQUE

ou outra estratégia de idempotência.

Portanto:

ACID
   ≠
IDEMPOTÊNCIA

ACID também não substitui:

tratamento de retries
deduplicação
regras de negócio
recovery da aplicação
restartability

Essa distinção tornou-se ainda mais importante quando o mainframe começou a conversar intensamente com:

APIs
MQ
eventos
cloud
microservices
Kafka

💳 CAPÍTULO 25 — O TESTE FINAL: DUAS COMPRAS, UM LIMITE

Chegamos à experiência final do laboratório.

Limite disponível:

R$ 1.000

Compra de Fry:

R$ 700

Compra de Bender:

R$ 600

As duas chegam praticamente juntas:

                 R$1000
                    │
             ┌──────┴──────┐
             ▼             ▼
          R$700           R$600

Agora ACID inteiro entra em ação.

Atomicity

Se a autorização depende de registrar movimento e atualizar o limite, precisamos da unidade transacional correta.

Não queremos:

limite reduzido
+
autorização inexistente

Consistency

Constraints, relacionamentos e regras implementadas precisam permanecer válidos.

Isolation

As duas compras não podem simplesmente tomar decisões independentes baseadas numa visão concorrente inadequada dos mesmos R$ 1.000.

Aqui entram isolamento, locking e concorrência.

Durability

Depois que a autorização foi efetivamente confirmada, uma falha posterior não deve simplesmente apagá-la da história.

Agora ACID não é mais uma pergunta de entrevista.

É dinheiro.


🧰 CAPÍTULO 26 — CHECKLIST DO PADAWAN COBOL

Sempre que encontrar:

EXEC SQL
   COMMIT
END-EXEC.

não passe correndo.

Pare e investigue:

  1. Qual Unit of Work termina aqui?

  2. Quais alterações pertencem à mesma operação de negócio?

  3. O que acontece se houver ABEND antes deste ponto?

  4. E imediatamente depois?

  5. Como funciona o restart?

  6. Existe risco de reprocessamento?

  7. A operação é idempotente?

  8. Quais outras transações concorrem pelos mesmos dados?

  9. Qual isolamento é necessário?

  10. Há CICS, MQ ou outros resource managers envolvidos?

  11. O programa trata deadlock e timeout adequadamente?

  12. As constraints representam todas as regras importantes ou parte delas vive no COBOL?

Essas doze perguntas valem mais do que decorar ACID para uma prova.


🗺️ CAPÍTULO 27 — O MAPA DO LABORATÓRIO FARNSWORTH

No final da aula, o Professor desenhou tudo no quadro:

                       A C I D
                          │
       ┌──────────────────┼──────────────────┐
       │                  │                  │
       ▼                  ▼                  ▼
  ATOMICITY          CONSISTENCY         ISOLATION
       │                  │                  │
       ▼                  ▼                  ▼
     UOW              Constraints          IRLM
   COMMIT              PK / FK             Locks
  ROLLBACK             UNIQUE            UR/CS/RS/RR
  BACKOUT              CHECK                │
       │               Business        ┌────┴────┐
       │                Rules          ▼         ▼
       │                           Deadlock   Timeout
       │
       └──────────────┐
                      ▼
                    LOG
                 ┌────┴────┐
                 ▼         ▼
               UNDO       REDO
                 │         │
                 ▼         ▼
            Atomicity  Durability
                           │
                ┌──────────┼───────────┐
                ▼          ▼           ▼
           Active Log  Archive Log  Recovery
                                       │
                                       ▼
                                     Restart

E acima disso:

                   USUÁRIO
                      │
                      ▼
                 CICS / BATCH
                      │
                      ▼
                    COBOL
                      │
                      ▼
                     Db2
          ┌───────────┼───────────┐
          ▼           ▼           ▼
     BUFFER POOL     IRLM         LOG
          │           │           │
          ▼           ▼           ▼
        DATA        LOCKING    RECOVERY
          │           │           │
          └───────────┼───────────┘
                      ▼
                     ACID

🧪 EPÍLOGO — GOOD NEWS, EVERYONE!

O jovem programador olhou novamente para o programa.

Naquela manhã, o código parecia simples:

EXEC SQL
   COMMIT
END-EXEC.

Agora ele enxergava outra coisa.

Via uma Unit of Work.

Via alterações ainda não confirmadas.

Via locks sendo administrados.

Via transações concorrentes.

Via IRLM.

Via páginas no buffer pool.

Via logging.

Via trabalho confirmado e não confirmado.

Via possibilidades de REDO e UNDO.

Via restart.

Via CICS coordenando recursos.

Via o batch que precisava saber de onde continuar.

Via o pagamento duplicado que ACID sozinho não impediria.

Via o deadlock escondido entre duas transações perfeitamente corretas quando observadas isoladamente.

Finalmente percebeu uma coisa que todo programador COBOL que trabalha seriamente com Db2 acaba descobrindo:

O SQL que você escreve é apenas a parte visível da transação.

Farnsworth colocou a mão sobre a enorme alavanca vermelha.

— Professor...

— Sim?

— Não toque nisso.

O velho cientista sorriu.

— Good news, everyone! Eu instalei um COMMIT!

— Professor, COMMIT não é backup.

Silêncio.

— Muito bem, jovem.

Farnsworth afastou lentamente a mão da alavanca.

E essa talvez seja a melhor definição do salto entre aprender SQL e começar a compreender Db2 for z/OS.

No começo aprendemos:

SELECT
INSERT
UPDATE
DELETE

Depois aprendemos:

COMMIT
ROLLBACK

Mas o verdadeiro salto acontece quando olhamos para um UPDATE e imediatamente pensamos:

Quem mais está acessando isto?

Qual é minha UOW?

Que lock posso provocar?

Qual isolamento preciso?

O que acontece se eu falhar agora?

O que já está confirmado?

Como faço restart?

Posso executar novamente?

Existe outro resource manager?

Como o Db2 recuperará isso?

Nesse momento você deixa de enxergar Db2 apenas como um lugar onde o COBOL guarda registros.

Você começa a enxergá-lo como uma máquina transacional construída para administrar simultaneamente mudança, concorrência e falha.

E essa é a grande sacada escondida nas quatro letras:

A C I D

ATOMICITY
   │
   └── Não deixe metade da história acontecer.

CONSISTENCY
   │
   └── Não transforme um estado válido em absurdo.

ISOLATION
   │
   └── Não deixe milhares de histórias simultâneas
       destruírem umas às outras.

DURABILITY
   │
   └── Depois de confirmar a história,
       não deixe uma falha apagá-la.

É por isso que bancos, cartões, seguradoras, companhias aéreas, varejistas e tantas outras empresas podem executar volumes enormes de transações sem depender da esperança de que "nada dê errado".

Porque coisas dão errado.

Programas sofrem ABEND.

Jobs são reiniciados.

Transações entram em deadlock.

Recursos ficam indisponíveis.

Sistemas precisam de recovery.

Mensagens podem ser reenviadas.

Aplicações concorrem.

Máquinas podem parar.

E às vezes alguém liga às 03:17 da manhã.

A genialidade não está em construir um universo onde falhas sejam impossíveis.

Está em construir um sistema que saiba o que fazer quando elas inevitavelmente acontecerem.

Farnsworth apagou as luzes do laboratório.

Na tela permaneceu apenas uma mensagem:

DSNE610I NUMBER OF ROWS DISPLAYED IS 1

E, ao lado dela, uma pequena anotação:

*> GOOD NEWS, EVERYONE.
*> SQLCODE = 0.

☕ Bem-vindo ao Db2 no mainframe, Padawan. Aqui até o caos precisa respeitar a Unit of Work.

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