Entendendo números crescentes na prática
Muita gente confunde número crescente com simplesmente "ordem ascendente", mas quando você vai implementar um sistema de numeração sequencial em produção, as coisas complicam rápido. O conceito básico é trivial — é apenas uma sequência onde cada termo é maior ou igual ao anterior —, mas a aplicação real envolve problemas de integridade, concorrência e rastreamento que não aparecem em definições de dicionário.
O que é número crescente
Um número crescente, no sentido mais útil do termo, é uma sequência numérica em que cada elemento subsequente tem valor igual ou superior ao anterior. Na prática administrativa, isso se traduz em códigos sequenciais atribuídos a documentos, processos, notas fiscais, protocolos e afins. O exemplo mais simples é uma série como 1, 2, 3, 4, 5. Um pouco mais complexa, mas ainda comum, seria 1001, 1002, 1005, 1006 — note que o 1003 e 1004 foram pulados, o que já quebra a idealização ingênua de que sequência crescente é sempre contínua. O que eu quero deixar claro desde o começo é que a ideia de "sequência perfeita" não sobrevive ao contato com a realidade. Num sistema real, registros são cancelados, transações falham, processos são arquivados sem gerar número, e você acaba com lacunas. Isso não invalida o conceito, só significa que você precisa tratar a numeração como aproximada, não absoluta.
Numa implementação típica em banco de dados, você armazena o último número atribuído em uma tabela de configuração e incrementa por unidade toda vez que um novo registro entra. Parece simples até alguém tentar gerar dois números ao mesmo tempo e obter duplicidade. Já vi isso acontecer em sistemas legados onde o controle de concorrência era inexistente — dois usuários cliavam no botão de gerar protocolo no mesmo segundo e o sistema entregava o mesmo número crescente para dois documentos diferentes. A correção foi adicionar uma trava de nível de tabela com SERIALIZABLE no isolation level, o que aumentou o tempo de resposta em cerca de 30 milissegundos mas eliminou completamente a colisão.
Como funciona na prática
A lógica central é um ciclo de leitura-incremento-gravação. Você lê o último valor, soma um, salva. O problema é que esse ciclo não é atômico por padrão. Se duas threads entram nesse processo simultaneamente, ambas leem o mesmo valor, ambas incrementam o mesmo valor, e ambas gravam o mesmo resultado. O banco de dados não te salva aqui sem configuração explícita. Uma abordagem mais robusta usa sequences do PostgreSQL ou AUTO_INCREMENT bem configurado do MySQL. O PostgreSQL, por exemplo, oferece a função NEXTVAL(), que é intrinsecamente atômica — você chama e recebe um número garantidamente único sem precisar travar nada manualmente. Isso reduz o overhead de bloqueio para quase zero e elimina a necessidade de mecanismos paralelos de controle.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Outra nuance importante que quem está começando geralmente ignora: números crescentes não precisam ser estritamente incremento de 1 em 1. Em muitos contextos empresariais, usa-se incrementos variáveis ou prefixos alfanuméricos combinados com parte numérica crescente. Um protocolo pode seguir o formato "PROC-2024-0047", onde "PROC-2024-" é fixo e "0047" é a parte crescente zerada à esquerda. O zero à esquerda não é capricho estético — em ordenação alfabética, "47" vem antes de "6", o que quebra relatórios e exportações. Sempre use padding numérico. Também é comum precisar de múltiplas sequências crescentes coexistindo. Digamos que você tenha setores diferentes dentro da mesma organização e cada um precise de sua própria numeração sequencial independente. A solução mais limpa é ter uma tabela de controladores com chave composta por código_do_setor e último_numero, em vez de colunas separadas para cada setor. Isso escala muito melhor quando o número de setores cresce, o que inevitavelmente acontece.
Problemas que aparecem depois
Depois que o sistema já está rodando e os números crescentes estão sendo gerados há meses ou anos, começam a surgir questões que ninguém considerou na fase de projeto. A primeira é a questão dos gaps. Quando um processo é cancelado ou um registro é excluído, o número não é reutilizado — e não deveria ser. Reutilizar números crescentes gera ambiguidade histórica, dificulta auditoria e pode violar requisitos regulatórios em segmentos como saúde e financeiro. Eu tive um caso específico em que um cliente precisava provar a cronologia exata de abertura de Protocolos Administrativos para um processo de transparência pública. O sistema anterior usava trigger mal implementada e, ao analisar os logs, percebemos que havia 12 protocolos com numeração idêntica em diferentes sessões do dia. Como não havia timestamp preciso vinculado à geração do número, não conseguimos determinar qual era o válido. A solução foi migrar para uma tabela de auditoria com INSERT-trigger que registrava usuário, IP, data/hora e número atribuído de forma atômica, usando um sequence do banco. O processo de migração levou cerca de 3 horas para 14 mil registros, incluindo validação cruzada.
Outro problema recorrente é a formatação. Números crescentes com milhar separador (ex: 1.000.001) parecem úteis em relatórios impressos, mas causam dor de cabeça em integrações, importações CSV e consultas SQL. Separe sempre a apresentação da armazenamento. Guarde como inteiro, formate na camada de exibição. Há também a questão do reinício de sequência. Alguns sistemas resetam a numeração crescente anualmente ou por exercício fiscal. Isso é aceitável desde que o prefixo data ou período faça parte do código completo, mas gera confusão quando alguém tenta ordenar registros de anos diferentes sem considerar o prefixo. Um "número crescente" de 2023 (que vai de 1 a 500) parece menor que um de 2024 (que começa em 1), mas na verdade é posterior. A solução é usar uma chave composta ou um número absoluto crescente com subsequência para exibição.
Limitações reais
Não existe solução perfeita aqui. Sequences de banco de dados são confiáveis, mas sofrem em cenários de alta concorrência extrema — mais de 500 operações por segundo de geração de número, por exemplo, onde o bottleneck passa a ser o lock do sequence e não sua lógica. Nesses casos, pré-alocação de ranges por worker distribui a carga de forma significativamente mais eficiente. Já sistemas baseados em aplicação, sem suporte nativo de sequence, são intrinsicamente frágeis. Qualquer falha de rede, timeout ou rollback parcial pode fazer dois clientes receberem o mesmo número. Se você precisa de garantia absoluta de unicidade e não pode usar recursos do banco, considere umsnowflake-style ID generator, que produz identificadores únicos globais com componente temporal embutido e não depende de estado compartilhado.
O ponto final é que número crescente é um conceito simples com implicações práticas bastante complexas. A diferença entre um sistema que funciona e um que genera problemas de integridade depois de seis meses geralmente está em como você trata a atomicidade, a formatação e o controle de concorrência desde o início, não em correções tardias.