Gerador de UUID

Gere UUID — v4 aleatórios ou v7 ordenados por tempo — um a um ou em lotes.

Versão

122 bits aleatórios. Não revela nada sobre quando foi criado.

Quantos

A gerar…

O que é um UUID e porque existe

Um UUID — Universally Unique Identifier, chamado GUID na documentação da Microsoft — é um valor de 128 bits escrito como 32 dígitos hexadecimais no familiar agrupamento 8-4-4-4-12. O seu propósito é permitir que sistemas separados criem identificadores de forma independente, sem qualquer coordenação entre si, e ainda assim confiarem em que os resultados não colidirão. É isso que o distingue de uma coluna auto-incremental: dois servidores, dois clientes móveis offline num avião e uma tarefa em segundo plano podem criar registos no mesmo instante sem pedir autorização a ninguém.

A unicidade aqui é probabilística e não garantida. A versão 4 deixa 122 bits ao acaso, um espaço suficientemente grande para que, mesmo gerando milhares de milhões de valores, a probabilidade de uma repetição continue muito abaixo da de um disco corromper os dados em silêncio. Na prática pode tratá-lo como único; a matemática não é o elo fraco.

Versão 4 contra versão 7 — a decisão que importa

A versão 4 é aleatória de ponta a ponta. Não transporta informação nenhuma: nem quando foi criada, nem por quem, nem em que ordem. Isso é a sua maior força ou o seu defeito central, consoante o sítio onde a colocar.

A versão 7, normalizada no RFC 9562 em 2024, substitui os primeiros 48 bits por uma marca temporal Unix em milissegundos e preenche o resto com aleatoriedade. Como o tempo vem primeiro e o valor se lê da esquerda para a direita, ordenar identificadores v7 como texto simples também os ordena cronologicamente.

Não é uma diferença cosmética. As bases de dados guardam as chaves primárias num índice B-tree ordenado. Insira chaves v7 e cada linha nova aterra no extremo direito da árvore, ao lado da anterior — as páginas onde escreve mantêm-se em memória e o índice cresce arrumado. Insira chaves v4 e cada escrita cai numa posição aleatória, a base de dados toca numa página diferente de cada vez, a taxa de acertos na cache desce e o índice fragmenta-se. Numa tabela grande e movimentada a diferença no débito de inserções é substancial, e é por isso que v7 foi adotado tão depressa para chaves primárias.

  • Escolha v7 para chaves primárias, identificadores de eventos e registos, e tudo o que quiser ordenar ou consultar por intervalo de data de criação.
  • Escolha v4 quando o identificador aparecer num sítio não fidedigno e não puder deixar escapar nada — incluindo o facto de um registo ter sido criado mesmo antes de outro.
  • Qualquer uma serve para um ID de correlação, uma chave de idempotência ou um nome de ficheiro, onde a ordem não interessa.

A contrapartida é exatamente essa fuga: um identificador v7 diz a quem o vir, ao milissegundo, quando foi criado. Para o ID de uma linha isso é normalmente inofensivo e muitas vezes útil. Para um token de reposição de palavra-passe ou uma ligação pública de partilha é informação que não pretendia publicar — e esses não deviam ser UUID de todo, mas tokens aleatórios de um gerador de segredos dedicado.

A ordem dentro do mesmo milissegundo

Uma subtileza que apanha muitas implementações de v7: o hardware moderno gera muito mais do que um identificador por milissegundo. Se dois valores partilharem a marca temporal, a sua ordem é decidida pelos bits aleatórios que se seguem — ou seja, ao acaso. Gere cinquenta num ciclo apertado e obtém cinquenta valores apenas aproximadamente ordenados, perdendo precisamente a propriedade pela qual escolheu v7.

O RFC 9562 resolve isto com um contador monótono, e esta ferramenta implementa-o: os 12 bits imediatamente a seguir à marca temporal contam para cima dentro de um milissegundo, pelo que um lote é estritamente crescente e não apenas aproximado. Se o contador encher — mais de 4096 valores no mesmo milissegundo — o gerador pede emprestado o milissegundo seguinte em vez de dar a volta e emitir um valor que ordene antes do anterior. O relógio a andar para trás, o que acontece com correções NTP, é tratado da mesma maneira.

Lendo um valor v7 da esquerda para a direita, tomando 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b como exemplo:

  • 0190a1b2-c3d4 — a marca temporal Unix de 48 bits em milissegundos. Como vem primeiro, a ordem do texto é a ordem do tempo.
  • 7 — o dígito de versão, que é o que torna isto um v7 e não um v4.
  • e5f — o contador monótono de 12 bits, que incrementa dentro de um mesmo milissegundo.
  • 8 — os bits de variante, fixados pelo RFC 9562 para todos os UUID modernos (sempre 8, 9, a ou b).
  • a9b-0c1d2e3f4a5b — os restantes 62 bits, puramente aleatórios.

Guardar e usar UUID

A forma canónica é em minúsculas com hífenes, e o RFC 9562 diz que os geradores devem emitir exatamente isso — razão pela qual esta ferramenta não oferece opções de formato. Ainda assim vai encontrar outras grafias: em maiúsculas e entre chavetas nas ferramentas da Microsoft, e sem hífenes onde alguém quis uma coluna mais curta. São todos os mesmos 128 bits, e as comparações devem ignorar maiúsculas e minúsculas.

Onde isto conta mesmo é no armazenamento. Um UUID tem 16 bytes, mas a forma textual tem 36 caracteres — por isso guardá-lo como texto mais do que duplica o espaço na linha e, mais importante, em todos os índices que o incluam. Use um tipo nativo onde exista um:

uuid                      -- PostgreSQL: tipo nativo de 16 bytes
BINARY(16)                -- MySQL: compacto; CHAR(36) desperdiça 20 bytes/linha
uniqueidentifier          -- SQL Server
crypto.randomUUID()       // JavaScript: só v4, exige contexto seguro
uuid.uuid4() / uuid7()    # Python: v4 na biblioteca padrão; v7 por biblioteca

Um último cuidado: um UUID identifica, não autoriza. Como não podem ser adivinhados, é tentador tratar como privado um URL não listado que contenha um. Mas os identificadores escapam — por registos, histórico do navegador, cabeçalhos referrer e capturas de ecrã — por isso tudo o que precisa mesmo de proteção continua a precisar de uma verificação de permissões a sério por trás.

Perguntas frequentes

Devo usar v4 ou v7?
Use v7 para chaves primárias e tudo o que for ordenar por data de criação: a marca temporal à cabeça mantém as inserções agrupadas no fim do índice em vez de espalhadas por ele. Use v4 quando o identificador não puder revelar nada, nem sequer quando foi criado.
Dois UUID podem ser iguais?
É possível mas extraordinariamente improvável. A versão 4 tem 122 bits aleatórios, por isso mesmo depois de gerar milhares de milhões de valores a probabilidade de colisão continua muito abaixo da de o armazenamento os corromper em silêncio.
O que aconteceu às versões 1, 3 e 5?
A versão 1 codifica uma marca temporal e o endereço MAC da máquina, o que revela a identidade do hardware e nem sequer pode ser produzido num navegador. As versões 3 e 5 derivam um UUID de forma determinística a partir de um espaço de nomes e um nome usando MD5 ou SHA-1 — útil quando a mesma entrada tem de dar sempre o mesmo identificador, mas é um trabalho diferente de gerar um novo.
Um UUID é suficientemente seguro como token secreto?
Um UUID v4 não pode ser adivinhado, mas um v7 codifica abertamente a sua hora de criação, e nenhum deles foi pensado como credencial. Para reposições de palavra-passe, tokens de sessão ou ligações de partilha, gere um segredo aleatório dedicado e verifique permissões no servidor em vez de confiar em que o identificador é difícil de adivinhar.
Porque é que o meu lote de v7 não fica perfeitamente ordenado noutras ferramentas?
Porque muitas implementações saltam o contador monótono. Quando vários valores partilham um milissegundo, a ordem fica entregue aos bits aleatórios seguintes. Esta ferramenta implementa o contador do RFC 9562, por isso um lote gerado aqui é estritamente crescente.
Como devo guardar um UUID numa base de dados?
Num tipo nativo de 16 bytes onde exista — uuid no PostgreSQL, uniqueidentifier no SQL Server, BINARY(16) no MySQL. Guardar em vez disso a forma textual de 36 caracteres mais do que duplica o espaço usado na linha e em cada índice que inclua a coluna.
São gerados nos vossos servidores?
Não. São gerados no seu navegador com crypto.getRandomValues, a fonte criptográfica de aleatoriedade da plataforma — a mesma que o crypto.randomUUID usa. Nenhum valor é enviado para lado nenhum, e recarregar a página produz um conjunto inteiramente novo.