SQL Server na prática

Por que Identity e Sequence deixam lacunas no SQL Server

Entenda lacunas causadas por rollback e cache, recupere chaves geradas e separe identificadores técnicos da numeração exigida pelo negócio.

Um valor identity ausente não prova que alguém excluiu uma linha. O SQL Server pode atribuir um número a uma inserção posteriormente revertida, sem desfazer a atribuição. Tratar identity como um contador sem lacunas gera falsos alertas e pode incentivar tentativas perigosas de reaproveitar identificadores.

Uma chave técnica responde a qual linha está sendo referenciada. Um número de negócio pode representar a posição de um documento em um processo de emissão. Esses requisitos têm ciclos de vida distintos. Separá-los impede que detalhes do armazenamento definam silenciosamente a política de numeração.

Observar alocação e confirmação separadamente

O exemplo usa uma tabela temporária e mantém a primeira linha confirmada para mostrar claramente a sequência.

CREATE TABLE #Tickets (
    TicketId int IDENTITY(1,1) PRIMARY KEY,
    Note nvarchar(80) NOT NULL
);
INSERT #Tickets(Note) VALUES (N'First committed row');
BEGIN TRANSACTION;
INSERT #Tickets(Note) VALUES (N'This row is rolled back');
ROLLBACK TRANSACTION;
INSERT #Tickets(Note) VALUES (N'Next committed row');
SELECT TicketId, Note FROM #Tickets ORDER BY TicketId;
DROP TABLE #Tickets;

Os identificadores restantes são 1 e 3. O número 2 foi atribuído à inserção revertida. Não falta uma linha confirmada: a transação removeu corretamente sua gravação, enquanto o mecanismo de alocação continuou.

IDENTITY pertence a uma tabela. SEQUENCE é um objeto de esquema independente, cujos valores podem ser pedidos antes da inserção e compartilhados entre tabelas. Isso ajuda quando a chave precisa ser conhecida antecipadamente, mas também torna normais os números alocados e não utilizados. Rollback não recupera valores de sequência.

O cache melhora a eficiência e pode criar lacunas adicionais quando valores reservados são perdidos em uma parada inesperada. Desativá-lo reduz essa causa específica, mas não devolve números de operações revertidas ou abandonadas. NO CACHE não garante numeração sem lacunas.

Separe ainda geração e unicidade. Uma chave primária ou restrição única deve proteger o identificador armazenado. Reseed, inserções explícitas de identity e sequências cíclicas podem causar colisões sem essa proteção. São ações de migração controlada, não consertos rotineiros de números ausentes.

Recuperar os valores realmente gerados

Ler MAX(Id) e somar um não prevê o próximo número com segurança. Outra sessão pode inserir entre a leitura e a escrita. A diferença entre maior identificador e quantidade de linhas também não mede exclusões de forma confiável.

Em uma inserção de uma linha, SCOPE_IDENTITY retorna a última identidade gerada no escopo atual. @@IDENTITY pode refletir uma identidade criada por um gatilho em outro escopo. Para várias linhas, OUTPUT inserted.Id devolve as chaves reais, mas sua ordem não deve ser associada automaticamente à ordem de entrada. Use uma correlação explícita.

Valores retornados por OUTPUT não comprovam que a transação inteira confirmou. Uma falha posterior ou rollback pode desfazer a gravação. Notificações externas devem acompanhar a conclusão confirmada do negócio e possuir recuperação para resultados de commit desconhecidos.

A ordem dos identificadores também não equivale à ordem dos commits. Uma transação pode receber o número menor e confirmar depois de outra. Relatórios precisam de horário explícito e contrato de ordenação; consumidores que não podem perder alterações precisam de um mecanismo de captura apropriado.

Planejar capacidade e numeração de negócio

A consulta lista colunas identity e os últimos valores alocados.

SELECT OBJECT_SCHEMA_NAME(object_id) AS SchemaName,
       OBJECT_NAME(object_id) AS TableName,
       name AS ColumnName,
       TYPE_NAME(user_type_id) AS DataType,
       seed_value, increment_value, last_value
FROM sys.identity_columns
ORDER BY SchemaName, TableName;

Monitore o intervalo restante conforme tipo, valor inicial, direção do incremento e taxa de alocação. Uma identity int positiva tem teto finito, e inserções malsucedidas também consomem números. Excluir linhas antigas não aumenta essa capacidade.

A migração para bigint pode afetar chaves estrangeiras, índices adicionais, parâmetros, exportações e tipos na aplicação. Planeje-a antes do esgotamento em vez de tratá-la como uma alteração emergencial de coluna.

Se o negócio exige uma sequência documental controlada, atribua o número no momento correto de emissão, armazene-o separadamente e defina como representar cancelamentos. Um contador transacional pode serializar a atribuição e limitar a vazão. Dividi-lo por cliente, categoria ou período só é válido quando a regra de negócio permite.

Teste emissão concorrente, cancelamento, rollback e repetições próximas ao commit. A garantia útil é uma política explicada e aplicada, não a aparência de valores consecutivos em uma coluna técnica que nunca foi projetada para prometê-los.

Referências técnicas: Microsoft Learn: IDENTITY property · Microsoft Learn: CREATE SEQUENCE · Microsoft Learn: OUTPUT clause.

Pergunte sobre este artigo

Tem alguma dúvida sobre este tema?

Conte o que você está avaliando ou onde encontrou dificuldades. Responderemos com uma recomendação prática.

Inquiries are not enabled in this preview.

Fazer uma pergunta sobre este artigo