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

segunda-feira, 4 de maio de 2026

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

 

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

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

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

O Db2 nunca esquece nada.

Cada:

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

deixa rastros.

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

🔥 O LOG DO Db2.

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

Porque no dia em que um:

-904
-911
-803
00C90084
RESOURCE UNAVAILABLE

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

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


☕ O QUE É O LOG DO Db2?

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

Tudo que altera dados gera registros de log.

O Db2 escreve:

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

Basicamente:

ALTERAÇÃO → LOG → DISCO

Antes mesmo da página ser gravada no tablespace.


🔥 ACTIVE LOGS vs ARCHIVE LOGS

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

🔹 Active Logs

São os logs online e ativos.

Ficam sendo usados continuamente.

Eles armazenam:

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

São críticos.

Perder active log é pesadelo nível apocalipse.


🔹 Archive Logs

Quando active logs ficam cheios:

  • Db2 descarrega,
  • copia,
  • arquiva.

Esses logs históricos viram:

ARCHIVE LOGS

Eles são usados para:

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

☕ COMO O Db2 ESCREVE NO LOG?

Muita gente acha que Db2 grava direto no disco.

Não.

Primeiro ele grava em:

🔥 LOG BUFFERS

na memória.

Depois:

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

forçam gravação nos:

ACTIVE LOG DATASETS

🔥 WRITE AHEAD LOGGING (WAL)

Aqui está o segredo do recovery moderno.

O Db2 segue:

🔥 WAL — Write Ahead Logging

Regra:

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

Isso garante:

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

Sem isso:
💀 corrupção.


☕ O QUE ACONTECE NUM COMMIT?

Quando o programa COBOL faz:

EXEC SQL COMMIT END-EXEC

o Db2:

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

O COMMIT é basicamente:

🔥 “Agora isso virou verdade oficial.”


☕ E NUM ABEND?

Aqui entra o terror psicológico do DBA.

Se ocorre:

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

o Db2 usa os logs para:

🔥 ROLLBACK

Ele desfaz tudo desde o último COMMIT.


🔥 TIPOS DE ERRO MAIS COMUNS


⚠️ SQLCODE -911 / -913

Deadlock ou timeout

Dois programas querem recursos incompatíveis.

Exemplo clássico:

  • batch segurando tabela,
  • online tentando atualizar.

DBA/Sysprog:

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

Programador COBOL:

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

⚠️ SQLCODE -904

Resource unavailable

Tablespace parado.
Utility rodando.
Objeto indisponível.

DBA:

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

Sysprog:

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

⚠️ SQLCODE -803

Duplicate key

Programador tentou inserir chave já existente.

Programador:

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

DBA:

  • verificar índice,
  • constraints,
  • integridade.

⚠️ SQLCODE -805

Package não encontrado

Clássico inferno de deploy.

DBA:

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

Sysprog:

  • SDSNLOAD,
  • STEPLIB,
  • DBRM libraries.

Programador:

  • garantir promote correto.

⚠️ 00C90084

Log full

Aqui o DBA começa a envelhecer rapidamente.

O active log lotou.

Possíveis causas:

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

DBA:

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

Programador:

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

☕ COMO FUNCIONA O RECOVERY?

Aqui mora a mágica do Db2.


🔥 FORWARD RECOVERY

Db2:

  1. restaura image copy,
  2. reaplica logs.

Resultado:
✅ banco volta até ponto desejado.


🔥 BACKOUT / ROLLBACK

Db2 usa:

  • before images,
  • undo records.

E desfaz alterações.


🔥 RESTART RECOVERY

Após crash do subsystem:

Db2:

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

Muitas vezes o usuário nem percebe.


☕ O PAPEL DO DBA

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

Ele:

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

Ferramentas clássicas:

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

☕ O PAPEL DO SYSPROG

O Sysprog atua na infraestrutura pesada.

Ele cuida:

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

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


☕ O QUE O PROGRAMADOR COBOL PRECISA ENTENDER?

Muito mais do que imaginam.

Porque SQL ruim gera:

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

🔥 Um bom programador Db2:

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


☕ O MAIOR ERRO DOS INICIANTES

Achar que:

COMMIT é só “salvar”.

Não.

COMMIT é:

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

É o coração do Db2 transacional.


🔥 CONCLUSÃO

O log do Db2 é praticamente:

🔥 a memória do banco.

Sem ele:

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

Quando você entende:

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

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

E começa a pensar como:

  • DBA,
  • sysprog,
  • arquiteto transacional.

E no universo mainframe…

isso muda tudo. ☕🔥

sexta-feira, 28 de novembro de 2025

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

 

Bellacosa Mainframe CICS e throughput

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

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


⚙️ TPS vs Throughput — visão Bellacosa Mainframe

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

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

💥 Tradução brutal:

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

Se você tem:

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

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


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

Quando você sai de uma região…

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

Agora você tem:

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

💣 E aqui vem o ponto que derruba sistema:

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


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

1. Consistência forte global

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

Resultado:

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

💣 Isso aqui mata performance.


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

👉 API Brasil → chama EUA → espera resposta

Resultado:

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

💣 É o equivalente moderno de:

“esperar fita montar pra continuar o batch”


3. Hotspot de dados

👉 Conta sendo acessada globalmente

Resultado:

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

💣 Clássico erro de modelagem.


☠️ O ERRO RAIZ (o mais perigoso)

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

🚫 Errado.

Isso é igual dizer:

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


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

Antes de falar de tecnologia, responda:

1. Tipo de operação

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

2. Consistência

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

💣 Regra de ouro:

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


3. Latência aceitável

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

👉 Isso define TUDO.


4. Distribuição geográfica

  • Usuário local?
  • Cross-border?

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


5. Perfil de carga

  • 📈 Constante?
  • 🚀 Pico violento?

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


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

Cenário:

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

Estratégia inteligente

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

Fluxo mental:

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

⚖️ O trade-off que ninguém escapa

Você sempre escolhe entre:

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

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


🔥 Conclusão estilo Bellacosa

Sistema financeiro não é sobre tecnologia.

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

💣 Engenheiro júnior:

“Qual tecnologia usar?”

🔥 Engenheiro sênior:

“Qual risco eu posso aceitar?”


☕ Verdade final (nível mainframe raiz)

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

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

quinta-feira, 12 de setembro de 2024

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

 

Bellacosa Mainframe apresenta cobol e db2

☕ Um Café no Bellacosa Mainframe

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

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

Nova York, 1973.

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

“Who loves ya, baby?”

Era o tenente Theo Kojak.

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

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

E existe algo profundamente mainframe em Kojak.

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

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

Troque a delegacia por um CPD.

Troque o assassinato por uma transação travada.

Troque as testemunhas por logs.

E dê ao tenente um terminal 3270.

Temos nosso novo investigador Db2.



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

O telefone toca.

O programador COBOL iniciante atende.

— Produção está parada.

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

Ele abre o fonte.

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

Olha novamente.

Nada parece errado.

Compilou.

Ontem funcionava.

O programador conclui:

— Deve ser o banco.

A porta do CPD abre.

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

— O banco, baby?

Silêncio.

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

E aí descobrimos nosso primeiro problema.



1. COBOL não executa SQL sozinho

Quando vemos:

EXEC SQL
    SELECT ...
END-EXEC

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

Não é.

COBOL e SQL são linguagens diferentes trabalhando juntas.

Podemos imaginar três responsabilidades:

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

O COBOL pode dizer:

“Preciso consultar o saldo desta conta.”

O SQL expressa:

SELECT SALDO
FROM CONTA
WHERE NUMERO = :WS-CONTA

E o Db2 precisa resolver como encontrar aquele registro eficientemente.

Kojak tira o pirulito da boca.

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

Exatamente.



2. O primeiro interrogatório: as Host Variables

Observe:

WHERE NUMERO = :WS-CONTA

Por que existe aquele :?

Porque WS-CONTA pertence ao programa hospedeiro.

É uma host variable.

Temos uma fronteira:

       COBOL                     SQL

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

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

No comando:

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

WS-CONTA fornece informação.

WS-SALDO recebe informação.

Parece simples.

Até aparecerem:

  • tipos incompatíveis;

  • valores NULL;

  • indicator variables;

  • truncamentos;

  • conversões;

  • nenhuma linha;

  • múltiplas linhas.

Kojak aponta para WS-CONTA.

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

Primeira regra da investigação:

entrada errada produz investigação errada.


3. O crime aconteceu antes da execução

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

Kojak balança a cabeça.

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

Quando existe SQL embutido, o SQL precisa ser processado.

No fluxo tradicional, podemos representar:

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

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

E acabamos de encontrar nosso primeiro suspeito misterioso.

DBRM.


4. DBRM — o dossiê policial do SQL

DBRM significa Database Request Module.

Não é o executável COBOL.

Não é a tabela.

Não é o banco.

Não é o programa completo.

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

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

Imagine:

PROGRAMA ABC123

SQL 001
SELECT SALDO...

SQL 002
UPDATE CONTA...

SQL 003
INSERT MOVIMENTO...

O Db2 precisará conhecer essas requisições.

O DBRM entra nessa história.

Kojak pega a pasta.

— Agora temos antecedentes.


5. BIND — agora leve o suspeito para a delegacia

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

BIND.

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

Temos:

DBRM
  │
  ▼
BIND PACKAGE
  │
  ▼
PACKAGE

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

Porque significa que existem dois universos relacionados:

             APLICAÇÃO

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

É perfeitamente possível que alguém diga:

“Mas o COBOL compilou!”

Ótimo.

Isso prova apenas uma parte da história.

Kojak sorri.

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


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

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

E aqui ocorre uma mudança mental importante.

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

Portanto:

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

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

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

O compilador não é Sherlock Holmes.

Muito menos Kojak.


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

Chegamos ao grande interrogatório.

Considere:

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

O programador declarou o que deseja.

Não escreveu:

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

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

O Db2 possui um optimizer.

Conceitualmente:

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

O optimizer avalia alternativas e custos.

Pode considerar índices.

Pode considerar outras estratégias.

O resultado dessa decisão é fundamental para performance.

Kojak olha para o programador:

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

Perfeito.


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

Agora temos uma situação deliciosa.

O programa não mudou.

O SQL não mudou.

A tabela não mudou estruturalmente.

Mas o desempenho ficou horrível.

Como?

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

É como Kojak perguntar:

— Quantas pessoas vivem neste prédio?

E alguém responder:

— Doze.

— Quando você contou?

— Em 1997.

Temos um problema.

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

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

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

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

Ela depende do ecossistema.


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

O iniciante aprende:

Índice deixa SELECT rápido.

Depois cria índice para tudo.

Parabéns.

Acabamos de transformar uma boa ideia em um novo incidente.

Índices possuem custo.

Precisam ser mantidos.

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

Portanto:

MAIS ÍNDICES

      não significa automaticamente

MAIS PERFORMANCE

A pergunta é:

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

Kojak provavelmente perguntaria:

— Esse índice estava onde na noite do crime?


10. O SQLCODE chega para depor

Executamos:

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

E agora?

Precisamos saber o resultado.

Entra o SQLCODE.

Didaticamente:

SQLCODE = 0
     │
     └── sucesso

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

SQLCODE negativo
     │
     └── erro

Um programador iniciante pode fazer:

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

Kojak quase engole o pirulito.

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

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

Isso pode ser perfeitamente normal.

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


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

Agora temos drama.

O programa retorna:

SQLCODE = -911

E alguém grita:

— Db2 caiu!

Não necessariamente.

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

Kojak sorri.

Finalmente um crime digno dele.

Imagine:

TRANSAÇÃO A

LOCK RECURSO 1
      │
      ▼
PRECISA RECURSO 2


TRANSAÇÃO B

LOCK RECURSO 2
      │
      ▼
PRECISA RECURSO 1

Temos:

A espera B

B espera A

Os dois poderiam esperar até a aposentadoria do programador.

O sistema precisa resolver a situação.

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


12. ACID — a divisão de crimes financeiros

Imagine uma transferência:

CONTA A = 1000
CONTA B =  500

TRANSFERÊNCIA = 100

Queremos terminar:

A = 900
B = 600

Não queremos:

A = 900
B = 500

porque o sistema caiu no meio.

É aqui que as propriedades ACID entram em cena:

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

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

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

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

Esse não é detalhe acadêmico.

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


13. COMMIT — pode liberar os suspeitos

Considere:

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

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

Mas imagine:

UPDATE A       OK
UPDATE B       OK
INSERT         ERRO

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

Entra:

ROLLBACK

Portanto:

        UNIT OF WORK

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

Essa dupla é parte central da engenharia transacional.


14. COMMIT também é performance

Agora vem uma sutileza importante.

Alguns iniciantes imaginam COMMIT apenas como:

salvar alterações.

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

Imagine um batch processando:

10 registros
100 registros
10.000 registros
10.000.000 registros

sem pensar adequadamente na estratégia de commit.

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

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

COMMIT a cada 1000

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

A estratégia depende da aplicação.


15. Então chega o CICS à delegacia

Até agora poderíamos estar pensando em batch.

Mas coloque a aplicação em ambiente transacional:

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

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

Temos simultaneamente:

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

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

Vira sobrevivência.


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

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

Aqui Kojak levantaria uma sobrancelha.

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

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

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

Portanto:

COBOL → DB2 Connect → Db2

não é uma representação universal.

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


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

Boa explicação.

Mas incompleta.

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

  • constraints;

  • integridade referencial;

  • views;

  • triggers;

  • stored procedures;

  • functions.

Então podemos pensar:

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

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

As responsabilidades precisam ser projetadas.

Não simplesmente presumidas.


18. Static SQL e Dynamic SQL entram na sala

Nosso exemplo:

EXEC SQL
    SELECT SALDO
    ...
END-EXEC

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

Conceitualmente:

STATIC SQL

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

Mas existe SQL dinâmico.

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

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

Novamente:

não existe “um é sempre melhor”.

Existe:

qual mecanismo atende melhor ao problema?


19. O crime perfeito: SELECT *

Kojak encontra:

SELECT *
FROM CLIENTE

Olha para o programador.

Olha novamente para a tela.

— Você precisa de todas essas colunas?

— Não.

— Então por que pediu?

Silêncio.

Essa pergunta vale ouro.

Evite transportar dados desnecessários.

Se precisa de:

NOME
SALDO

não peça quarenta colunas simplesmente porque:

SELECT *

é mais rápido de digitar.

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


20. Outro suspeito: SELECT dentro de LOOP

Agora Kojak encontra:

PERFORM 100000 TIMES

       SELECT ...

END-PERFORM

Acende a luz da sala de interrogatório.

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

O erro conceitual é tratar banco relacional como arquivo sequencial:

LEIA
LEIA
LEIA
LEIA
LEIA

SQL trabalha naturalmente com conjuntos.

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


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

Mas existe o extremo oposto.

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

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

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

SQL complexo não é automaticamente ruim.

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

Mas complexidade precisa possuir justificativa.

Legibilidade importa.

Manutenção importa.

Performance importa.

Testabilidade importa.


22. EXPLAIN — reconstruindo a cena do crime

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

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

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

Você começa a procurar pistas:

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

Kojak coloca fotografias na parede.

Agora temos uma investigação de verdade.

O programador deixa de dizer:

“Esse SELECT está lento.”

E começa a perguntar:

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

Essa diferença separa palpite de diagnóstico.


23. O verdadeiro CPD aparece

Finalmente afastamos a câmera.

O programador pensava que estava trabalhando com:

COBOL + DB2

Mas agora enxerga:

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

E ainda não terminamos.

Ao redor estão:

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

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


24. Kojak finalmente resolve o caso

Voltamos às 03:17.

O programa estava correto.

O SQL também.

O Db2 estava disponível.

O problema estava relacionado à concorrência.

Outra unidade de trabalho estava mantendo recursos necessários.

A transação esperou.

O limite foi atingido.

O SQL recebeu erro.

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

A mensagem apresentada ao operador foi:

ERRO NO BANCO

Ou seja:

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

Kojak olha para o programador.

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

— Sim.

Kojak coloca o pirulito na boca.

— Who loves ya, baby?


🍭 Easter egg — por que Kojak usa pirulito?

Esse detalhe é perfeito para nossa história.

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

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

Ou seja:

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

Qualquer semelhança com sistemas legados é absolutamente maravilhosa.

Um programador em 1984 cria:

05 WS-FLAG PIC X.

para resolver temporariamente um problema.

Quarenta anos depois:

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

😂


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

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

MOVE
COMPUTE
IF
EVALUATE
PERFORM

Isso é apenas a porta de entrada.

Depois vem:

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

E finalmente você percebe:

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

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

Essa é uma das coisas mais bonitas do mainframe.

Na superfície:

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

Debaixo:

               50 ANOS
                  DE
             ENGENHARIA
                  │
                  ▼
             WS-SALDO

O programador olha para a variável.

Depois olha para Kojak.

Finalmente compreendeu.

Não basta perguntar:

“O programa compilou?”

É preciso investigar:

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

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

Produção aceita evidência.

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

O programador pergunta:

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

Kojak sorri.

— Agora você sabe interrogar os suspeitos, baby.

E sai.

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

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

Fim do JOB.

IEF404I KOJAK - ENDED
IEF142I KOJAK STEP01 - COND CODE 0000

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

segunda-feira, 11 de setembro de 2023

📨 ALAN TURING E O MQ DOS AGENTES — A MENSAGEM CHEGOU DUAS VEZES

 

Bellacosa Mainframe e as mensagens em ia

☕ UM CAFÉ NO BELLACOSA MAINFRAME

📨 ALAN TURING E O MQ DOS AGENTES — A MENSAGEM CHEGOU DUAS VEZES

IBM MQ, agentes de IA, mensageria, filas, producers, consumers, delivery semantics, acknowledgements, commit, rollback, duplicate delivery, idempotência, ordering, correlation ID, message ID, poison messages, backout queues, dead-letter queues, retry, persistence, request/reply, COBOL, CICS, Db2 — e o dia em que Alan Turing descobriu que uma mensagem pode chegar duas vezes sem que ninguém tenha cometido o mesmo erro duas vezes.





🎬 PRÓLOGO — MAS EU JÁ FIZ ISSO!

03:17 da madrugada.

O telefone toca.

Nunca existe boa notícia às 03:17.

O operador atende.

— Produção.

Silêncio.

Depois:

— Temos dois pagamentos iguais.

O operador abre o terminal.

PAYMENT-ID.... P88271
VALUE......... 850.00
STATUS........ PROCESSED

Outra linha:

PAYMENT-ID.... P88271
VALUE......... 850.00
STATUS........ PROCESSED

O pequeno agente aparece na tela.

— Não fui eu!

Alan Turing entra no CPD carregando uma caneca de café.

— Interessante defesa.

— Professor, eu processei a mensagem uma única vez!

O operador consulta os logs.

03:16:51 GET MESSAGE
03:16:52 PROCESS PAYMENT
03:16:52 DB2 COMMIT OK
03:16:52 ...
03:16:53 AGENT RESTART
03:16:54 GET MESSAGE

Turing aponta para o intervalo.

— O que aconteceu entre o commit e a confirmação do consumo da mensagem?

Silêncio.

O administrador MQ olha para o administrador Db2.

O administrador Db2 olha para o programador COBOL.

O programador COBOL olha para o robô.

O robô olha para a porta.

Turing sorri.

— Acho que encontramos nosso próximo capítulo.

No quadro escreve:

PROCESSAR UMA MENSAGEM E CONFIRMAR QUE ELA FOI PROCESSADA NÃO SÃO NECESSARIAMENTE O MESMO EVENTO.

Bem-vindo ao MQ dos Agentes.



📨 CAPÍTULO 1 — MENSAGERIA COMEÇA COM UMA IDEIA MUITO SIMPLES

Imagine dois programas.

PROGRAMA-A

precisa pedir alguma coisa para:

PROGRAMA-B

Uma possibilidade seria A chamar B diretamente.

A ───────────────► B

Mas isso cria algumas dependências.

B precisa estar disponível.

A talvez precise esperar.

A precisa saber onde B está.

Se B estiver sobrecarregado, A sofre junto.

Mensageria introduz um intermediário.

A
│
▼
QUEUE
│
▼
B

A produz uma mensagem.

B consome depois.

Temos dois papéis clássicos:

PRODUCER

e:

CONSUMER.

O producer produz.

O consumer consome.

No meio:

QUEUE.

Simples.

Até produção começar.



📬 CAPÍTULO 2 — UMA FILA É UMA CAIXA POSTAL

Para o programador COBOL iniciante, imagine uma caixa postal.

O remetente coloca:

PEDIDO 12345

na caixa.

Ele não precisa esperar o funcionário responsável aparecer.

Depois o consumidor pega a mensagem.

PUT
↓
QUEUE
↓
GET

No universo IBM MQ podemos imaginar conceitualmente operações como:

MQPUT

e:

MQGET.

O produtor coloca.

O consumidor recupera.

Isso permite:

desacoplamento
processamento assíncrono
absorção de picos
integração entre plataformas
resiliência

Nosso agente pode agora receber trabalho através de mensagens.



🤖 CAPÍTULO 3 — O AGENTE VIROU CONSUMIDOR

Imagine:

CUSTOMER.EVENTS

recebendo:

CUSTOMER_UPDATED

Nosso agente escuta essa fila.

Chega:

CUSTOMER_ID = 12345
EVENT       = ADDRESS_CHANGED

O agente:

1. recebe
2. interpreta
3. consulta Db2
4. aplica regras
5. talvez chama ferramentas
6. produz resultado

Perfeito.

Mas aparece a primeira pergunta importante:

Quando podemos considerar essa mensagem realmente processada?

Quando o agente começou?

Não.

Quando terminou o raciocínio?

Talvez não.

Quando atualizou o Db2?

Ainda precisamos pensar.

Quando confirmou o consumo?

Agora estamos chegando perto do problema.



✉️ CAPÍTULO 4 — TODA MENSAGEM PRECISA DE IDENTIDADE

No JES2 dos Agentes aprendemos:

RUN-ID.

Agora precisamos identificar mensagens.

Conceitualmente:

MESSAGE-ID

Pode existir também:

CORRELATION-ID.

Imagine:

MESSAGE-ID..... M000881
CORRELATION-ID. C000042
RUN-ID......... A004821

Esses identificadores respondem perguntas diferentes.

MESSAGE-ID

Qual mensagem é esta?

CORRELATION-ID

A qual conversa, fluxo ou solicitação ela pertence?

RUN-ID

Qual execução do agente está processando?

Isso será ouro para observabilidade.


🔗 CAPÍTULO 5 — CORRELATION ID: ENCONTRE A CONVERSA NO MEIO DO CAOS

Imagine:

REQUEST
MESSAGE-ID M100
CORREL-ID C500

O serviço responde:

RESPONSE
MESSAGE-ID M101
CORREL-ID C500

São mensagens diferentes.

Mas pertencem à mesma conversa.

Em sistemas distribuídos isso é extremamente útil.

Podemos seguir:

USER REQUEST
     ↓
CICS
     ↓
MQ
     ↓
AGENT
     ↓
Db2
     ↓
ANOTHER QUEUE

Tudo associado a:

CORRELATION-ID C500.

Quando alguém pergunta:

O que aconteceu com a solicitação do cliente?

não precisamos procurar agulha no palheiro.


📦 CAPÍTULO 6 — A MENSAGEM PODE SOBREVIVER AO CONSUMIDOR

Aqui está uma das grandes vantagens de mensageria confiável.

O producer envia.

PUT MESSAGE

O consumer está desligado.

A mensagem pode permanecer na fila conforme sua configuração e características.

Depois:

CONSUMER START

Ele processa.

Isso é muito diferente de uma chamada síncrona simples.

No mundo dos agentes isso é poderoso.

O LLM pode estar indisponível.

O worker pode reiniciar.

A aplicação pode sofrer manutenção.

A mensagem continua aguardando.

Mas agora surge uma pergunta:

Quanto tempo?


⏰ CAPÍTULO 7 — MENSAGENS TAMBÉM ENVELHECEM

Olha quem voltou.

Nosso amigo do Db2:

TEMPO.

Imagine:

MESSAGE CREATED:
10:00

O consumidor consegue processar:

14:00.

Tecnicamente a mensagem chegou.

Mas ainda faz sentido?

Talvez seja:

GENERATE MONTHLY REPORT

Sem problema.

Talvez seja:

CUSTOMER IS CURRENTLY LOGGED IN

Quatro horas depois?

Provavelmente inútil.

Logo mensagens também possuem:

AGE
EXPIRY
BUSINESS VALIDITY.

O MQ dos Agentes encontra o Db2 dos Agentes.

Não basta perguntar:

A mensagem chegou?

Pergunte:

Ela ainda significa alguma coisa quando chegou?


💥 CAPÍTULO 8 — A MENSAGEM CHEGOU DUAS VEZES

Finalmente chegamos ao monstro.

Imagine:

GET M001

O agente processa.

INSERT PAYMENT
COMMIT

Tudo certo.

Mas antes de completar adequadamente o ciclo de consumo:

CRASH.

Quando volta, dependendo da arquitetura e semântica empregada, a mensagem pode estar novamente disponível.

GET M001

O agente grita:

— Eu já processei isso!

A infraestrutura responde:

— Prove.

😂

Bem-vindo à possibilidade de:

REDELIVERY.


🧠 CAPÍTULO 9 — POR QUE DUPLICATAS EXISTEM?

Porque sistemas distribuídos possuem pontos de falha.

Considere:

MESSAGE
↓
PROCESS
↓
DATABASE UPDATE
↓
ACKNOWLEDGE

Agora imagine falha exatamente aqui:

DATABASE UPDATE
↓
COMMIT
↓
💀 CRASH
↓
ACKNOWLEDGE

Do ponto de vista do banco:

SUCCESS.

Do ponto de vista da mensageria:

NÃO SEI SE ELE TERMINOU.

O sistema possui duas escolhas ruins.

Escolha A

Assumir que processou.

Pode perder mensagem.

Escolha B

Entregar novamente.

Pode duplicar processamento.

Sistemas confiáveis frequentemente preferem não perder trabalho.

Então seu consumidor precisa estar preparado para duplicatas quando a semântica e arquitetura permitirem redelivery.


🔁 CAPÍTULO 10 — AT-LEAST-ONCE

Uma semântica comum em sistemas de mensageria e processamento distribuído é:

AT-LEAST-ONCE

Ou seja:

A mensagem será processada pelo menos uma vez.

Isso pode significar:

1

ou:

2

ou, em situações problemáticas:

mais.

Então:

AT-LEAST-ONCE

não significa:

EXACTLY-ONCE.

Se o efeito da mensagem não puder acontecer duas vezes, precisamos projetar proteção.


🎯 CAPÍTULO 11 — EXACTLY-ONCE É O UNICÓRNIO DA DUNGEON

Todo mundo quer:

EXACTLY ONCE.

A mensagem chega uma vez.

É processada uma vez.

O efeito acontece uma vez.

Perfeito.

Mas sistemas distribuídos possuem:

falhas
timeouts
restarts
partições
retries

E cada fronteira transacional complica o problema.

Se MQ e Db2 participam de uma unidade coordenada adequadamente, podemos obter garantias transacionais fortes em cenários específicos.

Mas quando nosso agente chama:

Db2
REST API
email
LLM
CRM SaaS
payment service

a conversa muda.

Nem todos participam da mesma transação.

Por isso é perigoso jogar:

EXACTLY-ONCE

num slide como se fosse magia.


🛡️ CAPÍTULO 12 — IDEMPOTÊNCIA ENTRA COM UMA ESPADA

A solução prática frequentemente passa por:

IDEMPOTÊNCIA.

Uma operação idempotente pode ser repetida sem produzir efeitos adicionais indesejados depois da primeira aplicação bem-sucedida.

Exemplo perigoso:

ADD R$ 100 TO BALANCE

Execute duas vezes:

+100
+100

Resultado diferente.

Agora imagine:

SET PAYMENT P123 STATUS = PROCESSED

Executar novamente pode ser inofensivo dependendo da regra.

Ou:

PROCESS PAYMENT
WHERE PAYMENT_ID = P123
AND STATUS = PENDING

Depois da primeira execução:

STATUS = PROCESSED.

A segunda encontra:

NOT PENDING.

Nada acontece.

Muito melhor.


🪪 CAPÍTULO 13 — IDEMPOTENCY KEY

Outra técnica:

IDEMPOTENCY-KEY.

Exemplo:

IDEMPOTENCY-KEY = ORDER-9981-PAYMENT

Antes de executar:

SELECT STATUS
FROM PROCESSED_MESSAGES
WHERE IDEMPOTENCY_KEY = :KEY;

Se já existe:

ALREADY PROCESSED

não repetimos o efeito.

Se não existe:

PROCESS
STORE KEY
COMMIT

O detalhe crucial é tornar essa proteção suficientemente atômica para impedir dois consumidores concorrentes de passarem pela verificação simultaneamente.

Porque senão:

AGENT-A: não existe!
AGENT-B: não existe!

AGENT-A: processa!
AGENT-B: processa!

Parabéns.

Construímos uma deduplicação que duplica.

😂


🔐 CAPÍTULO 14 — MQ E Db2 PRECISAM CONVERSAR SOBRE COMMIT

Agora chegamos ao terreno favorito do mainframe.

Imagine:

MQGET
↓
UPDATE Db2
↓
COMMIT

Queremos que o consumo da mensagem e a alteração no banco tenham comportamento consistente.

Idealmente, dentro de um desenho transacional apropriado:

GET MESSAGE
+
UPDATE DATABASE
+
COMMIT

fazem parte de uma unidade lógica coerente.

Se falhar:

ROLLBACK.

A alteração do banco não fica pela metade e a mensagem pode permanecer disponível conforme a unidade de trabalho.

Esse é exatamente o tipo de problema que mainframes resolvem há décadas.


🧱 CAPÍTULO 15 — UNIT OF WORK VOLTOU

Nosso velho amigo:

UOW

Unit of Work.

Conceitualmente:

BEGIN UOW

GET MESSAGE
UPDATE DB2
INSERT AUDIT

COMMIT UOW

Se:

UPDATE DB2

falhar:

ROLLBACK.

O importante é definir claramente:

Quais efeitos pertencem à mesma unidade de consistência?

Para agentes, isso é essencial.

Porque eles tendem a fazer muitas coisas.


☠️ CAPÍTULO 16 — O PROBLEMA DAS AÇÕES EXTERNAS

Nosso agente:

GET MESSAGE
↓
UPDATE Db2
↓
SEND EMAIL
↓
CALL PAYMENT API
↓
POST MESSAGE

Rollback?

Db2:

— Posso ajudar.

MQ:

— Também.

E-mail:

— Já enviei.

API externa:

— Já cobrei.

Internet:

— Boa sorte.

😂

Essa é a fronteira entre transações locais/coordenadas e efeitos distribuídos externos.

Você precisa pensar em:

idempotência
compensação
outbox
inbox
deduplicação
reconciliação

e não simplesmente:

ROLLBACK EVERYTHING.

📤 CAPÍTULO 17 — O OUTBOX PATTERN

Imagine que precisamos:

UPDATE ORDER

e depois publicar:

ORDER_COMPLETED.

Problema clássico:

UPDATE Db2
COMMIT

CRASH

SEND MESSAGE

O pedido mudou.

A mensagem nunca saiu.

Ou:

SEND MESSAGE

CRASH

UPDATE Db2

Mensagem diz que aconteceu.

Banco diz que não.

Uma abordagem conhecida é o:

TRANSACTIONAL OUTBOX.

Dentro da mesma transação do banco:

UPDATE ORDER

INSERT INTO OUTBOX
   ORDER_COMPLETED

COMMIT

Depois outro processo publica registros da outbox.

Assim a intenção de publicar fica persistida junto com a alteração de negócio.

Ainda precisamos tratar duplicatas na publicação.

Mas removemos uma janela perigosa.


📥 CAPÍTULO 18 — INBOX PATTERN

Do outro lado podemos manter registro das mensagens consumidas.

INBOX
────────────────
MESSAGE_ID
PROCESSED_AT
STATUS

Chega:

M001.

Verificamos.

Não existe.

Processamos e registramos.

Chega novamente:

M001.

Existe.

DUPLICATE

Ignoramos ou retornamos o resultado anterior, conforme a aplicação.

Temos então:

OUTBOX

para publicação confiável e:

INBOX

para consumo controlado.


🧪 CAPÍTULO 19 — A MENSAGEM VENENOSA

Imagine:

MESSAGE M666

Chega.

Consumer tenta.

FAIL.

Volta.

Tenta.

FAIL.

Volta.

FAIL.

E continua:

FAIL
FAIL
FAIL
FAIL
FAIL

Talvez a mensagem tenha:

formato inválido
campo impossível
versão incompatível
regra não suportada
dados corrompidos

Ela nunca funcionará sem intervenção.

Chamamos informalmente esse tipo de caso de:

POISON MESSAGE.

Nosso agente não deveria ficar mastigando veneno eternamente.


☠️ CAPÍTULO 20 — BACKOUT QUEUE

Em ambientes IBM MQ, podemos projetar tratamento para mensagens que repetidamente causam rollback/backout.

Depois de determinado limite:

BACKOUT COUNT > THRESHOLD

a aplicação pode encaminhar a mensagem para uma:

BACKOUT QUEUE.

Assim:

NORMAL QUEUE

continua processando mensagens saudáveis.

E a problemática vai para investigação.

Conceitualmente:

QUEUE
  │
  ▼
CONSUMER
  │
  ├── SUCCESS → DONE
  │
  └── FAIL
       │
       ▼
    RETRY
       │
       ▼
 THRESHOLD?
   │       │
  NO      YES
   │       │
 retry     ▼
       BACKOUT QUEUE

Isso impede que uma única mensagem bloqueie eternamente o fluxo.


⚰️ CAPÍTULO 21 — DEAD-LETTER QUEUE NÃO É EXATAMENTE A MESMA COISA

Aqui precisamos separar conceitos.

Uma:

DEAD-LETTER QUEUE

é tradicionalmente associada a mensagens que o sistema não consegue entregar ou encaminhar ao destino esperado por determinados problemas de entrega.

Uma:

BACKOUT QUEUE

pode ser usada pela aplicação para mensagens que foram entregues, mas falham repetidamente durante processamento e sofrem backout.

No discurso moderno muita gente usa “DLQ” genericamente para qualquer fila de mensagens problemáticas.

Mas no universo IBM MQ a distinção operacional é útil.

O mainframeiro olha e diz:

Nome correto evita reunião de duas horas.


🔁 CAPÍTULO 22 — RETRY PRECISA TER CÉREBRO

Falhou.

Tentamos novamente?

Depende.

Erro:

HTTP 503

Talvez.

Erro:

INVALID CUSTOMER ID

Provavelmente não.

Erro:

TIMEOUT

Talvez.

Erro:

SCHEMA VERSION UNSUPPORTED

Repetir cem vezes provavelmente produzirá cem fracassos.

Portanto:

RETRYABLE ERROR

e:

NON-RETRYABLE ERROR

deveriam ser tratados diferentemente.

Retry não é religião.

É política.


⏳ CAPÍTULO 23 — EXPONENTIAL BACKOFF

Imagine 10.000 agentes.

Serviço externo cai.

Todos tentam novamente:

NOW.

O serviço tenta recuperar.

Dez mil chamadas chegam.

Ele cai novamente.

Chamamos isso de:

RETRY STORM.

Uma estratégia:

1s
2s
4s
8s
16s

é exponential backoff.

Adicione:

JITTER

para não fazer todos acordarem exatamente juntos.

4.1s
3.7s
4.8s

Agora reduzimos o efeito manada.

WLM agradece.


🚂 CAPÍTULO 24 — E SE AS MENSAGENS CHEGAREM FORA DE ORDEM?

Imagine:

M1:
CUSTOMER_CREATED

depois:

M2:
CUSTOMER_BLOCKED.

Queremos:

M1 → M2.

Mas o consumidor observa:

M2 → M1.

Agora pode concluir:

Não existe cliente para bloquear.

Depois cria o cliente.

Resultado:

ACTIVE.

Mas deveria estar:

BLOCKED.

O conteúdo estava correto.

As mensagens estavam corretas.

A ordem estava errada.

Mais um monstro.


🔢 CAPÍTULO 25 — SEQUÊNCIA TAMBÉM É DADO

Podemos adicionar:

ENTITY-ID...... CUSTOMER-123
SEQUENCE....... 42

Depois:

ENTITY-ID...... CUSTOMER-123
SEQUENCE....... 43.

O consumidor recebe 43 antes de 42.

Pode:

esperar
reordenar
rejeitar
reconciliar

dependendo da arquitetura.

Mas precisa saber que existe ordem.

Sem informação de sequência, talvez seja impossível perceber o problema.


🧩 CAPÍTULO 26 — ORDEM GLOBAL É CARA E MUITAS VEZES DESNECESSÁRIA

Precisamos de todas as mensagens do sistema inteiro em ordem?

Provavelmente não.

Talvez precisemos apenas manter ordem por:

CUSTOMER-ID

ou:

ORDER-ID

ou:

ACCOUNT-ID.

Isso permite paralelismo entre entidades diferentes.

CUSTOMER A → ordered
CUSTOMER B → ordered
CUSTOMER C → ordered

mas A, B e C podem ser processados simultaneamente.

O segredo é perguntar:

Qual é a menor fronteira dentro da qual a ordem realmente importa?


🕰️ CAPÍTULO 27 — ATRASADA NÃO SIGNIFICA FORA DE ORDEM

Outra distinção.

Uma mensagem pode chegar:

30 minutos atrasada

mas ainda na ordem correta.

Ou:

100 ms depois

mas fora de ordem em relação a outra.

Temos conceitos diferentes:

LATENCY
ORDERING
FRESHNESS.

Não misture.

O Db2 dos Agentes nos ensinou:

dado tem idade.

O MQ acrescenta:

a notícia sobre o dado também tem idade.


📰 CAPÍTULO 28 — EVENT TIME E PROCESSING TIME

Imagine evento:

EVENT_TIME:
10:00:01

Chega ao consumidor:

PROCESSING_TIME:
10:00:09.

São tempos diferentes.

Isso pode ser extremamente relevante.

Se o agente analisa:

O que aconteceu às 10:00?

precisa considerar:

EVENT TIME.

Se pergunta:

Quando processamos?

usa:

PROCESSING TIME.

Misturar os dois pode gerar análises absurdas.


🤖 CAPÍTULO 29 — O AGENTE PRECISA SABER QUE O EVENTO NÃO É O ESTADO ATUAL

Chega mensagem:

10:00
CUSTOMER_STATUS_CHANGED
ACTIVE → BLOCKED

Nosso agente recebe às:

10:10.

Antes de executar ação crítica, talvez precise consultar Db2.

Porque às:

10:05

o cliente pode ter sido:

UNBLOCKED.

Então a mensagem descreve:

ALGO QUE ACONTECEU

e não necessariamente:

COMO O MUNDO ESTÁ AGORA.

Essa distinção é gigantesca.

EVENT ≠ CURRENT STATE.


🗄️ CAPÍTULO 30 — MQ E Db2 CONTAM HISTÓRIAS DIFERENTES

Db2 frequentemente responde:

Qual é o estado armazenado?

MQ frequentemente transporta:

Algo aconteceu.

Exemplo:

Db2:
STATUS = ACTIVE

Evento antigo:

CUSTOMER_BLOCKED.

Se o agente tratar o evento antigo como estado atual:

problema.

Por isso, para ações críticas:

EVENT
↓
INTERPRET
↓
READ CURRENT STATE
↓
REVALIDATE
↓
ACT.

Nosso princípio do Db2 dos Agentes volta novamente.


🔄 CAPÍTULO 31 — EVENTUAL CONSISTENCY

Em sistemas distribuídos, diferentes componentes podem não refletir a mesma mudança exatamente no mesmo instante.

Imagine:

SYSTEM A
STATUS = BLOCKED

Evento viaja.

Enquanto isso:

SYSTEM B
STATUS = ACTIVE.

Alguns milissegundos ou segundos depois:

SYSTEM B
STATUS = BLOCKED.

Durante esse intervalo:

A ≠ B.

Isso não significa necessariamente corrupção.

Pode ser uma consequência do modelo de propagação.

Agentes precisam compreender isso.

Dois sistemas podem temporariamente apresentar visões diferentes.

Lembra dos dois agentes do Db2?

Eles voltaram.


📊 CAPÍTULO 32 — OBSERVABILIDADE DA FILA

Nosso SDSF dos Agentes ganha novos campos.

Imagine:

QUEUE........ CUSTOMER.EVENTS
DEPTH........ 18,442

OLDEST MSG... 00:07:31
PUT RATE..... 920/s
GET RATE..... 710/s

CONSUMERS.... 24
BACKOUTS..... 17
RETRIES...... 2,881

Agora conseguimos enxergar:

QUEUE DEPTH

Mas profundidade sozinha não basta.

18 mil mensagens pode ser terrível.

Ou normal.

Precisamos de contexto.

Talvez mais importante seja:

OLDEST MESSAGE AGE.

Se a fila cresce e a mensagem mais velha envelhece:

temos backlog real.


📈 CAPÍTULO 33 — PRODUCER MAIS RÁPIDO QUE CONSUMER

Imagine:

PRODUCER = 1000 msg/s
CONSUMER = 700 msg/s

Diferença:

+300 msg/s.

Depois de um minuto:

18,000 messages

Depois de uma hora:

1,080,000.

A fila absorve pico.

Mas não derrota matemática.

😂

Se a entrada continuamente supera a saída:

BACKLOG ↑
LATENCY ↑
MESSAGE AGE ↑

Precisamos:

mais consumers
mais capacidade
reduzir trabalho
priorizar
aplicar backpressure

WLM aparece novamente.


🚦 CAPÍTULO 34 — BACKPRESSURE

Se consumidores não conseguem acompanhar produtores, precisamos evitar crescimento ilimitado.

Isso pode envolver:

rate limiting
quotas
producer throttling
queue limits
load shedding
priority

Mensageria desacopla componentes.

Mas desacoplamento não significa capacidade infinita.

Fila é amortecedor.

Não buraco negro.


🧰 CAPÍTULO 35 — CHECKLIST DO MQ DOS AGENTES

Antes de colocar um agente consumindo mensagens, responda:

1. Quem produz?

PRODUCER?

2. Quem consome?

CONSUMER?

3. A mensagem é persistente quando necessário?

Defina de acordo com criticidade.

4. Ela pode ser entregue novamente?

Projete assumindo que sim quando sua semântica permitir.

5. O processamento é idempotente?

Se não, por quê?

6. Existe idempotency key?

Defina.

7. Existe MESSAGE-ID?

Sempre saiba qual mensagem está tratando.

8. Existe CORRELATION-ID?

Rastreie o fluxo.

9. A ordem importa?

Defina a fronteira.

10. Existe sequence number?

Quando necessário.

11. A mensagem expira?

Defina validade.

12. Existe retry?

Classifique erros.

13. Existe backoff?

Evite tempestades.

14. Existe poison message handling?

Tenha backout ou quarentena adequada.

15. Existe DLQ?

Monitore.

16. A mensagem representa evento ou estado?

Não confunda.

17. Precisa revalidar no Db2?

Para ações críticas, provavelmente.

18. O commit inclui quais recursos?

Defina UOW.

19. Existem efeitos externos?

Planeje idempotência ou compensação.

20. Conseguimos provar o que aconteceu?

Logs, traces, IDs e timestamps.


🥚 EASTER EGG — A MENSAGEM IMORTAL

04:12.

O operador percebe:

BACKOUT COUNT = 847.

— Professor...

Turing aproxima-se.

MESSAGE-ID = M666

— Há quanto tempo?

FIRST DELIVERY:
1999-12-31 23:59:58

Silêncio.

O programador COBOL arregala os olhos.

— Isso está tentando processar desde o bug do milênio?

O administrador MQ responde:

— Ninguém teve coragem de apagar.

O pequeno robô pergunta:

— O que ela contém?

Abrem.

CUSTOMER-ID = 000000001
ACTION      = MIGRATE
FORMAT      = VERSION-0

Turing olha.

— Algum consumidor suporta versão zero?

Todos:

— Não.

— Então por que continuam tentando?

Silêncio.

O operador responde:

— Retry policy.

Turing pega o café.

— Qual?

RETRY = FOREVER.

Turing fecha os olhos.

No fundo do CPD alguém sussurra:

Ela não é uma mensagem... agora ela é patrimônio histórico.

😂


🧬 CAPÍTULO 36 — NOSSO MAINFRAME DOS AGENTES GANHOU SISTEMA NERVOSO

Nossa arquitetura agora possui:

RACF
↓
QUEM PODE?
PF3
↓
POSSO PARAR?
SDSF
↓
O QUE ESTÁ FAZENDO?
MAXCC
↓
FUNCIONOU?
WLM
↓
QUEM RECEBE RECURSOS?
JES2
↓
QUEM COMEÇA E QUANDO?
CICS
↓
QUANTO TEMPO O HUMANO PODE ESPERAR?
Db2
↓
QUAL REALIDADE O AGENTE ESTÁ VENDO?

E agora:

MQ
↓
COMO A NOTÍCIA VIAJA ENTRE OS AGENTES?

Começamos a montar algo muito interessante.


🏰 CAPÍTULO 37 — O SISTEMA OPERACIONAL CONCEITUAL DOS AGENTES

Turing desenha:

                        HUMANO
                           │
                           ▼
                        CICS
                           │
               ┌───────────┴───────────┐
               │                       │
               ▼                       ▼
             AGENT                    MQ
               │                       │
               │                  ┌────┴────┐
               │                  ▼         ▼
               │               AGENT-B   AGENT-C
               │                  │         │
               └──────────┬───────┴─────────┘
                          ▼
                         Db2

Acima:

JES2
SCHEDULING

Ao redor:

WLM
CAPACITY

Na porta:

RACF
AUTHORITY

Na sala de operações:

SDSF
OBSERVABILITY

E sobre as mensagens:

MESSAGE-ID
CORRELATION-ID
SEQUENCE
TIMESTAMP
VERSION

Agora agentes não são apenas pequenos cérebros isolados.

Eles formam:

UM SISTEMA DISTRIBUÍDO.

E sistemas distribuídos possuem regras próprias.


🧠 CAPÍTULO 38 — O PROGRAMADOR COBOL TEM OUTRA VANTAGEM INESPERADA

Para muita gente:

event-driven architecture
message queues
async processing
retries

parecem invenções moderníssimas.

O mainframeiro olha para MQ e diz:

Sente-se, jovem.

😂

Porque aplicações corporativas trabalham com:

mensageria
filas
commit
rollback
correlation
persistence
backout
recovery

há décadas.

Claro que tecnologias modernas acrescentaram:

cloud
Kafka
microservices
containers
serverless
agents
LLMs.

Mas a pergunta fundamental continua:

Como dois componentes independentes trocam trabalho sem transformar cada falha em catástrofe?

Essa pergunta é antiga.

E continua excelente.


☕ CAPÍTULO 39 — O AGENTE PRECISA SER DESCONFIADO

Um consumidor robusto não deveria pensar:

Recebi uma mensagem. Vou obedecer.

Deveria perguntar:

Quem enviou?
Posso confiar?
Qual schema?
Qual versão?
Já processei?
Está na ordem?
Ainda é válida?
Tenho autorização?
Preciso consultar o estado atual?
Posso executar duas vezes?
Como confirmo?
Como desfaço?

Isso parece paranoia.

Em produção chamamos de:

ENGENHARIA.


🎭 CAPÍTULO 40 — EVENTO NÃO É ORDEM

Outra regra importante para agentes.

Mensagem:

CUSTOMER_CHANGED_ADDRESS

significa:

O endereço mudou.

Não significa automaticamente:

Faça alguma coisa perigosa.

O agente precisa interpretar eventos dentro de política.

Uma arquitetura segura separa:

FACT

de:

DECISION

e:

ACTION.

Assim:

EVENT
↓
OBSERVE
↓
VALIDATE
↓
DECIDE
↓
AUTHORIZE
↓
ACT

Essa separação reduz o risco de transformar qualquer mensagem numa ordem administrativa.

RACF agradece novamente.


🔐 CAPÍTULO 41 — MENSAGEM TAMBÉM PRECISA DE ZERO TRUST

Nosso agente não deveria confiar numa mensagem apenas porque ela apareceu numa fila.

Considere:

identity
authorization
queue permissions
message integrity
origin
schema validation
content validation

Uma mensagem malformada ou maliciosa pode tentar fazer o agente:

CALL TOOL
TRANSFER MONEY
DELETE DATA

Logo:

MQ

não elimina segurança.

Ele apenas transporta dados.

Autorização continua sendo outra camada.


🧾 CAPÍTULO 42 — SCHEMA É O COPYBOOK DA MENSAGEM

O programador COBOL conhece isso imediatamente.

Mensagem:

01 PAYMENT-MESSAGE.
   05 MSG-VERSION       PIC 9(04).
   05 PAYMENT-ID        PIC X(20).
   05 CUSTOMER-ID       PIC 9(09).
   05 AMOUNT            PIC S9(11)V99 COMP-3.
   05 EVENT-TIMESTAMP   PIC X(26).

Isso define estrutura.

Mas lembramos do Db2 dos Agentes:

ESTRUTURA NÃO É SEMÂNTICA.

Precisamos saber:

AMOUNT é em BRL?
PAYMENT-ID é único?
EVENT-TIMESTAMP usa qual timezone?
CUSTOMER-ID pode ser zero?
MSG-VERSION 0002 é compatível?

O copybook voltou.

Ele nunca foi embora.


🔄 CAPÍTULO 43 — VERSIONAMENTO DE MENSAGEM

Hoje:

VERSION 1

Amanhã precisamos adicionar:

CURRENCY.

Criamos:

VERSION 2.

Mas ainda existem consumidores antigos.

Agora precisamos pensar:

backward compatibility
forward compatibility
schema evolution

Nosso agente deve saber:

Consigo interpretar esta versão?

Se não:

QUARANTINE

é melhor do que:

VOU CHUTAR.

Especialmente quando “chutar” movimenta dinheiro.


🌊 CAPÍTULO 44 — A FILA É UM AMORTECEDOR, NÃO UM MILAGRE

Turing desenha:

PRODUCER
████████████████████████
          ↓
       QUEUE
~~~~~~~~~~~~~~~~~~~~~~~~
          ↓
CONSUMER
██████████

A fila absorve diferença temporária.

Mas se producer permanece mais rápido:

QUEUE DEPTH ↑

até algum limite operacional.

Portanto monitoramos:

depth
oldest age
put rate
get rate
consumer count
failure rate
backout count

Uma fila crescente é uma mensagem.

Ironicamente:

A própria fila está tentando falar com você.


🏁 CAPÍTULO 45 — A REGRA DE OURO

Alan Turing escreve no quadro:

MESSAGE RECEIVED
≠
BUSINESS ACTION COMPLETED

Depois:

BUSINESS ACTION COMPLETED
≠
MESSAGE ACKNOWLEDGED

Depois:

MESSAGE ACKNOWLEDGED
≠
WORLD STILL UNCHANGED

O pequeno robô fica olhando.

— Então eu não posso confiar em nada?

Turing sorri.

— Pode.

— Em quê?

— Em protocolos, transações, IDs, versões, políticas, observabilidade e verificações.

— Parece trabalhoso.

— É.

— E se eu simplesmente confiar que tudo dará certo?

Do fundo do CPD, cinco administradores começam a rir.


☕ EPÍLOGO — RECEBIDO NÃO SIGNIFICA TERMINADO

07:02.

A equipe da manhã chega.

Nosso agente recebe:

MESSAGE-ID..... M004821
CORREL-ID...... C009912
EVENT.......... PAYMENT_REQUESTED
PAYMENT-ID..... P88271
AMOUNT......... 850.00
SEQUENCE....... 42
EVENT-TIME..... 07:02:01

Ele verifica:

SCHEMA......... OK
VERSION........ SUPPORTED
AUTHORITY...... OK
DUPLICATE...... NO
ORDER.......... OK
FRESHNESS...... OK

Consulta Db2.

CURRENT STATE.. VALID

Inicia unidade de trabalho.

PROCESS PAYMENT
INSERT AUDIT
REGISTER MESSAGE

Confirma.

COMMIT.

Resultado:

SUCCESS.

Alguns milissegundos depois:

💥

O worker cai.

Reinicia.

A mensagem aparece novamente.

O velho agente teria gritado:

Já fiz isso!

O novo apenas consulta:

IDEMPOTENCY-KEY = P88271.

Resposta:

ALREADY PROCESSED.

Nenhum pagamento duplicado.

Nenhuma madrugada destruída.

Nenhum DBA perseguindo robôs pelo corredor.

O agente registra:

DUPLICATE DELIVERY
BUSINESS EFFECT SKIPPED
STATUS = SAFE

Turing toma o primeiro café da manhã.

O programador pergunta:

— Então a duplicata deixou de ser um problema?

— Não.

— Mas não aconteceu nada.

— Exatamente.

O programador pensa.

Turing continua:

— Engenharia confiável não é construir um universo onde falhas nunca acontecem.

Aponta para a tela:

REDELIVERY DETECTED

— É construir um sistema no qual falhas esperadas deixam de virar desastres inesperados.

O pequeno robô levanta a mão.

— Professor?

— Sim?

— Posso apagar a mensagem de 1999?

Do outro lado do CPD o administrador MQ grita:

— NÃO! PRIMEIRO FAZ BACKUP!

😂

Turing fecha o terminal.

Na tela permanece:

MQ
────────────────────────

MESSAGE-ID...... M004821
DELIVERY........ 2
PROCESSING...... IDEMPOTENT
BUSINESS EFFECT. ONCE
STATUS.......... SAFE

COMMIT.......... OK

E embaixo:

A MENSAGEM PODE CHEGAR NOVAMENTE.

O EFEITO NÃO PRECISA ACONTECER NOVAMENTE.

Essa é talvez a grande lição do MQ dos Agentes.

Porque quando centenas de inteligências artificiais começarem a conversar entre si, delegando tarefas, publicando eventos, recebendo respostas, reiniciando workers, atravessando APIs, bancos, filas e nuvens, não bastará perguntar:

A mensagem chegou?

Teremos de perguntar:

Qual mensagem?

De quem?

Quando?

Em qual ordem?

Quantas vezes?

Ainda é válida?

Já foi processada?

O efeito foi confirmado?

Posso executar novamente?

E se eu cair exatamente agora?

O mainframe conhece essa paranoia há décadas.

E talvez por isso tenha tanta coisa para ensinar aos agentes.

MQGET
   ↓
VALIDATE
   ↓
DEDUPLICATE
   ↓
REVALIDATE
   ↓
PROCESS
   ↓
COMMIT
   ↓
ACKNOWLEDGE

Alan Turing olha para o fluxo.

Toma mais um gole.

E acrescenta apenas uma linha:

IF IN DOUBT
   DO NOT CHARGE THE CUSTOMER TWICE.

READY

☕ UM CAFÉ NO BELLACOSA MAINFRAME

🤖 Alan Turing entra no CPD

O mapa dos agentes de IA explicado por um mainframer

Esta série acompanha a evolução de uma ideia: compreender os problemas modernos dos agentes de inteligência artificial usando conceitos conhecidos por quem trabalha com mainframe, IBM Z e sistemas corporativos.

A viagem começa pelas pessoas e pela experiência de uso, passa por observabilidade, priorização e execução, chega às transações, estado e mensageria e termina na organização hierárquica do contexto.

01
FEV / 2023

🧠 O currículo invisível da inteligência artificial

Antes de construir agentes inteligentes precisamos preparar as pessoas que trabalharão com eles. Técnica, pensamento crítico, conhecimento de negócio, segurança, ética e responsabilidade formam o currículo que nem sempre aparece no certificado.

02
MAR / 2023

🤖 A UX dos agentes

Quando uma IA deixa de apenas responder e começa a executar ações, sua interface precisa mostrar objetivos, progresso, permissões e resultados. PF3, MAXCC e RACF tornam-se excelentes analogias para controle, retorno e privilégio mínimo.

04
MAI / 2023

⚖️ O WLM dos agentes

CPU, GPU, tokens, APIs e bancos de dados são recursos finitos. O Workload Manager inspira uma discussão sobre prioridades, objetivos de serviço, importância do trabalho e distribuição dinâmica de recursos entre agentes.

06
JUL / 2023

⚡ O CICS dos agentes

Uma coisa é uma IA produzir texto. Outra é permitir que ela execute operações reais de negócio. CICS introduz a conversa sobre processamento transacional, concorrência, segurança e integridade.

07
AGO / 2023

🗄️ O Db2 dos agentes

Agentes precisam manter estado, checkpoints, decisões e resultados. O Db2 fornece o ponto de partida para discutir unidade de trabalho, consistência, COMMIT, ROLLBACK e recuperação.

10
SET / 2026

☕ Alan Turing entra no CPD — O mapa completo

O artigo-âncora reúne toda a evolução da ideia: pessoas, UX, observabilidade, prioridade, orquestração, transações, estado, mensageria e contexto transformam artigos independentes em uma arquitetura conceitual para agentes de IA.

🖥️ Leitor da série

Selecione qualquer capítulo acima para abri-lo normalmente. O painel abaixo é apenas um recurso adicional de navegação.

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