SQL SERVER
TEMPDB CHEIO:
POR QUE ISSO
PARA TUDO —
E COMO RESOLVER.
O tempdb chegou ao limite. O SQL Server para de processar queries. Aplicações começam a retornar erros. O telefone toca.
Não é a sua instância inteira que travou — mas parece. Porque o tempdb é um recurso compartilhado por todas as sessões, todos os bancos de dados, todas as operações rodando naquela instância. Quando ele enche, todo mundo sente.
Este artigo explica por que isso acontece, como identificar o responsável em minutos com as queries certas — e o que fazer para resolver agora e evitar a recorrência.
1DB
Uma única instância SQL Server. Um único tempdb. Compartilhado por todas as sessões simultâneas.
100%
Quando o tempdb enche, 100% das operações que dependem dele falham — não só a query culpada.
5×
As cinco causas que respondem por praticamente todos os casos de tempdb cheio em produção.
01
O QUE É O TEMPDB E POR QUE ELE CRESCE
O tempdb é o banco de dados de rascunho do SQL Server. Toda sessão o usa, continuamente, para operações que precisam de espaço temporário: tabelas temporárias, variáveis de tabela, resultados intermediários de sorts e joins, version store de snapshot isolation, rebuilds de índice com SORT_IN_TEMPDB, operações de cursor, DBCC CHECKDB — a lista é longa.
Diferente de outros bancos de dados, o tempdb é recriado a cada reinicialização do SQL Server. Isso significa que os objetos que ficaram lá de sessões anteriores somem. Mas também significa que você não pode fazer backup, não pode restaurar, e não pode depender dele como armazenamento durável.
O problema começa quando o crescimento do tempdb não é monitorado. Sem alertas configurados, o primeiro sinal de que algo está errado é a aplicação retornando erros — ou o DBA de plantão recebendo uma ligação às 3h da manhã.
"O tempdb é como o ar condicionado do escritório — ninguém percebe quando está funcionando. Quando para, todo mundo reclama ao mesmo tempo."
02
AS TRÊS CATEGORIAS DE USO — ONDE ESTÁ O PROBLEMA
Antes de sair investigando sessão por sessão, você precisa saber em qual categoria o espaço está sendo consumido. O SQL Server divide o uso do tempdb em três categorias distintas, e a causa — e a solução — são completamente diferentes para cada uma:
User Objects — tabelas temporárias e variáveis de tabela
São os objetos criados explicitamente pelo desenvolvedor ou pela aplicação: #temp_tables, ##global_temp_tables, @table_variables, índices em tabelas temporárias e o resultado de SELECT INTO no tempdb. Se user objects estão consumindo espaço excessivo, o problema está numa query ou stored procedure que está criando tabelas temporárias muito grandes.
Internal Objects — sort, hash join e spills
São criados pelo próprio SQL Server durante a execução de queries. Sorts que não cabem na memória "spillam" para o tempdb. Hash joins com estimativas de cardinalidade ruins fazem o mesmo. Operações com GROUP BY, ORDER BY, UNION, DISTINCT em grandes volumes também geram internal objects. Se internal objects estão consumindo espaço, o problema está em queries mal otimizadas ou em configuração de memória insuficiente.
Version Store — snapshot isolation e RCSI
Quando o banco de dados usa Read Committed Snapshot Isolation (RCSI) ou Snapshot Isolation, o SQL Server mantém versões antigas das linhas no tempdb para que transações em andamento possam ler dados consistentes sem bloquear writers. O version store cresce quando há transações de longa duração que impedem o garbage collector de limpar versões antigas. Se version store está consumindo espaço, o problema está em transações que não são commitadas ou rollbackeadas por muito tempo.
-- Identificar qual categoria está consumindo o tempdb
-- Execute esta query quando o tempdb estiver crescendo
SELECT
SUM(unallocated_extent_page_count) AS [Espaço livre (páginas)],
SUM(version_store_reserved_page_count) AS [Version Store (páginas)],
SUM(internal_object_reserved_page_count) AS [Internal Objects (páginas)],
SUM(user_object_reserved_page_count) AS [User Objects (páginas)],
SUM(mixed_extent_page_count) AS [Mixed Extents (páginas)]
FROM sys.dm_db_file_space_usage;
-- Converter para MB: multiplique por 8 e divida por 1024
-- Exemplo: 10000 páginas × 8 / 1024 = ~78 MBO resultado mostra imediatamente qual categoria domina o consumo. Version Store alto → investigue transações longas. Internal Objects alto → investigue queries com spill. User Objects alto → investigue tabelas temporárias grandes.
03
AS 5 CAUSAS MAIS COMUNS — E COMO IDENTIFICAR CADA UMA
Com a categoria identificada, o próximo passo é encontrar a sessão ou query responsável. Para cada uma das cinco causas mais comuns, há uma query de diagnóstico específica.
Causa 1 — Tabela temporária gigante em stored procedure
Sintoma: user_object_reserved_page_count alto na query de diagnóstico.
O cenário clássico: uma stored procedure cria um #temp e popula com um SELECT * sem WHERE, ou com um join sem filtro adequado. Em produção, essa tabela temporária pode ter milhões de linhas e consumir gigabytes de tempdb.
O problema muitas vezes existia há meses no ambiente — mas só se manifestou quando o volume de dados cresceu o suficiente para tornar o comportamento crítico.
-- Encontrar as sessões consumindo mais espaço em user objects
SELECT
su.session_id,
es.login_name,
es.host_name,
es.status,
(su.user_objects_alloc_page_count -
su.user_objects_dealloc_page_count) * 8 / 1024.0 AS [User Objects MB],
SUBSTRING(st.text, 1, 200) AS [Query atual]
FROM sys.dm_db_session_space_usage su
INNER JOIN sys.dm_exec_sessions es
ON su.session_id = es.session_id
OUTER APPLY sys.dm_exec_sql_text(es.sql_handle) st
WHERE su.session_id >= 50 -- remove sessões de sistema
AND (su.user_objects_alloc_page_count -
su.user_objects_dealloc_page_count) > 0
ORDER BY [User Objects MB] DESC;Causa 2 — Query spillando para disco (sort ou hash join)
Sintoma: internal_object_reserved_page_count alto.
Quando o SQL Server estima que uma query vai processar X linhas mas na prática processa 10X — por estatísticas desatualizadas ou estimativas de cardinalidade ruins — ele aloca memória para X linhas. Quando a memória acaba, o restante vai para o tempdb como "spill". Em queries de alto volume, um spill pode consumir dezenas de gigabytes.
Você consegue identificar isso no plano de execução: operadores de Sort ou Hash Match com um símbolo de aviso amarelo indicam que houve spill para tempdb.
-- Encontrar sessões com maior uso de internal objects (spills)
SELECT
su.session_id,
es.login_name,
(su.internal_objects_alloc_page_count -
su.internal_objects_dealloc_page_count) * 8 / 1024.0 AS [Internal MB],
er.wait_type,
SUBSTRING(st.text, 1, 300) AS [Query atual]
FROM sys.dm_db_session_space_usage su
INNER JOIN sys.dm_exec_sessions es
ON su.session_id = es.session_id
LEFT JOIN sys.dm_exec_requests er
ON su.session_id = er.session_id
OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) st
WHERE su.session_id >= 50
AND (su.internal_objects_alloc_page_count -
su.internal_objects_dealloc_page_count) > 0
ORDER BY [Internal MB] DESC;Internal objects altos combinados com wait_type como PAGEIOLATCH_EX ou PAGEIOLATCH_SH confirmam o spill para disco.
Causa 3 — Version Store crescendo por transação aberta longa
Sintoma: version_store_reserved_page_count alto e crescendo continuamente.
Com RCSI ou Snapshot Isolation habilitados, o SQL Server mantém versões antigas de cada linha modificada no tempdb. O garbage collector remove essas versões quando não há mais nenhuma transação ativa que precise delas. Se existe uma transação que foi aberta e nunca foi commitada ou rollbackeada — por um bug na aplicação, por uma sessão esquecida, por um processo travado — o version store não consegue ser limpo e continua crescendo.
-- Encontrar a transação mais antiga que está impedindo
-- o garbage collector de limpar o version store
SELECT
transaction_id,
transaction_sequence_num,
elapsed_time_seconds,
session_id,
is_snapshot,
transaction_type
FROM sys.dm_tran_active_snapshot_database_transactions
ORDER BY elapsed_time_seconds DESC;
-- Se elapsed_time_seconds for > 300 (5 minutos),
-- investigue a sessão correspondente-- Tamanho atual do version store em MB
SELECT
COUNT(*) AS [Páginas no Version Store],
COUNT(*) * 8 / 1024 AS [Version Store MB]
FROM sys.dm_tran_version_store;Causa 4 — DBCC CHECKDB ou rebuild de índice com SORT_IN_TEMPDB
Sintoma: internal objects crescendo rapidamente durante janela de manutenção.
DBCC CHECKDB — especialmente em bancos de dados grandes — usa o tempdb extensivamente para materializar versões dos dados durante a verificação de consistência. Da mesma forma, rebuilds de índice com a opção SORT_IN_TEMPDB = ON movem as operações de sort para o tempdb, o que melhora a performance do rebuild mas aumenta o consumo de espaço temporário.
Se esses processos estão rodando em paralelo com a carga de produção, o impacto pode ser severo.
-- Verificar operações de manutenção ativas
SELECT
session_id,
command,
percent_complete,
estimated_completion_time / 1000 / 60 AS [Minutos restantes],
SUBSTRING(st.text, 1, 200) AS [Comando]
FROM sys.dm_exec_requests er
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) st
WHERE command IN ('DBCC', 'ALTER INDEX', 'DBCC CHECKDB')
ORDER BY session_id;Causa 5 — Tempdb subdimensionado com autogrowth excessivo
Sintoma: crescimento rápido, eventos de autogrowth frequentes no Event Log, spike de I/O durante o crescimento.
Se o tempdb foi configurado com tamanho inicial pequeno e autogrowth habilitado, cada evento de autogrowth pausa todas as threads que estão aguardando o arquivo crescer. Em produção de alta concorrência, isso se manifesta como lentidão generalizada e timeouts na aplicação — mesmo que haja espaço em disco disponível.
O SQL Server 2019+ melhora isso com Instant File Initialization para o tempdb, mas a configuração adequada de tamanho inicial ainda é fundamental.
-- Ver tamanho, crescimento e localização dos arquivos do tempdb
SELECT
name AS [Arquivo],
physical_name AS [Caminho],
size * 8 / 1024 AS [Tamanho atual MB],
growth AS [Crescimento (páginas ou %)],
is_percent_growth AS [Crescimento em %?],
max_size AS [Tamanho máximo]
FROM tempdb.sys.database_files
ORDER BY file_id;is_percent_growth = 1, o autogrowth está configurado em percentual — o que significa que quanto maior o arquivo, maior o evento de crescimento. Troque para crescimento fixo em MB para comportamento previsível.DISCOVERY GRATUITO
Quer que um DBA Senior analise o seu tempdb?
Se o seu tempdb está crescendo de forma imprevisível ou você teve um episódio de "tempdb cheio" nos últimos 30 dias, é sinal de que há um problema estrutural no ambiente — não apenas um evento pontual. Em uma sessão de discovery gratuita de 30 minutos, nossa equipe analisa as métricas do seu ambiente e identifica a causa raiz.
Agendar diagnóstico gratuito →Ou fale agora: wa.me/551140636900
04
COMO RESOLVER — AÇÕES IMEDIATAS E DEFINITIVAS
Com a causa identificada, a resolução depende do cenário. Aqui estão as ações por ordem de urgência.
Ação imediata: liberar espaço sem reiniciar o SQL Server
A primeira tentativa deve ser matar a sessão responsável pelo consumo — especialmente se for uma transação longa no version store ou uma tabela temporária de uma sessão específica.
-- Ver as sessões que mais consomem tempdb (todas as categorias)
SELECT
su.session_id,
es.login_name,
es.host_name,
es.program_name,
(su.user_objects_alloc_page_count +
su.internal_objects_alloc_page_count) * 8 / 1024.0 AS [Total MB],
(su.user_objects_alloc_page_count -
su.user_objects_dealloc_page_count) * 8 / 1024.0 AS [User Objects MB],
(su.internal_objects_alloc_page_count -
su.internal_objects_dealloc_page_count) * 8 / 1024.0 AS [Internal MB],
SUBSTRING(st.text, 1, 300) AS [SQL atual]
FROM sys.dm_db_session_space_usage su
INNER JOIN sys.dm_exec_sessions es
ON su.session_id = es.session_id
OUTER APPLY sys.dm_exec_sql_text(es.sql_handle) st
WHERE su.session_id >= 50
ORDER BY [Total MB] DESC;
-- Após identificar o session_id culpado:
-- KILL [session_id];
-- Exemplo: KILL 127;KILL, confirme com a equipe de desenvolvimento o impacto de encerrar aquela sessão. Um KILL em transação longa pode gerar um rollback longo — e o rollback também usa tempdb.Se o tempdb está 100% cheio: aumentar o tamanho emergencialmente
Quando o tempdb está completamente cheio e o servidor não consegue processar nem a query de diagnóstico, a solução de emergência é expandir o arquivo diretamente.
-- Aumentar o tamanho do tempdb imediatamente
-- Substitua o valor pelo tamanho que faz sentido para o seu ambiente
ALTER DATABASE tempdb
MODIFY FILE (
NAME = 'tempdev',
SIZE = 20480MB -- 20 GB — ajuste conforme necessário
);
-- Se houver múltiplos arquivos de dados, repita para cada um
-- Todos os arquivos de dados do tempdb devem ter o mesmo tamanhoEssa é uma ação de emergência. O problema estrutural que causou o crescimento ainda precisa ser identificado e resolvido.
Configuração correta para prevenir recorrência
Após resolver o episódio imediato, a configuração adequada do tempdb previne a recorrência:
-- 1. Número de arquivos de dados: regra geral
-- Use o número de CPUs lógicas, até no máximo 8 arquivos
-- (para instâncias com 8+ CPUs, 8 arquivos é suficiente)
-- 2. Todos os arquivos devem ter o MESMO tamanho inicial
-- e o MESMO crescimento automático (em MB, não em %)
ALTER DATABASE tempdb
MODIFY FILE (NAME = 'tempdev', SIZE = 8192MB, FILEGROWTH = 1024MB);
-- Repita para todos os arquivos com os mesmos valores
-- 3. Verificar se Snapshot Isolation está habilitado
-- (isso determina se o version store será usado)
SELECT name, is_read_committed_snapshot_on, snapshot_isolation_state_desc
FROM sys.databases
WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb');
-- 4. Monitorar o version store continuamente
SELECT
DB_NAME(database_id) AS [Banco],
reserved_page_count * 8 / 1024 AS [Version Store MB],
elapsed_time_seconds / 60 AS [Minutos ativos]
FROM sys.dm_tran_active_snapshot_database_transactions
ORDER BY reserved_page_count DESC;Separar o tempdb em disco dedicado
Uma prática recomendada que muitas empresas ignoram: o tempdb deve estar em um volume de disco separado dos bancos de dados de produção. Quando o tempdb cresce inesperadamente e preenche o disco, ele não deve competir com o log de transações ou os arquivos de dados dos bancos de produção. Discos separados eliminam esse risco e melhoram a performance de I/O do tempdb.
05
MONITORAMENTO PROATIVO: DETECTAR ANTES QUE ENCHA
A causa raiz de todo episódio de "tempdb cheio" em produção é a mesma: ninguém estava monitorando. As queries de diagnóstico acima funcionam quando o problema já está acontecendo. O que evita o problema é um monitoramento contínuo que alerta quando o uso se aproxima de um threshold crítico.
Alerta de threshold — configurar no SQL Server Agent
-- Script para monitorar uso do tempdb e gerar alerta
-- Configure como SQL Server Agent Job com agendamento de 5 minutos
DECLARE @total_mb FLOAT, @used_mb FLOAT, @pct_used FLOAT;
SELECT
@total_mb = SUM(size * 8.0 / 1024),
@used_mb = SUM(FILEPROPERTY(name, 'SpaceUsed') * 8.0 / 1024)
FROM tempdb.sys.database_files
WHERE type = 0; -- apenas arquivos de dados, não log
SET @pct_used = (@used_mb / @total_mb) * 100;
-- Gera alerta se uso > 80%
IF @pct_used > 80
BEGIN
RAISERROR(
'ALERTA: TempDB em %.1f%% de capacidade. Total: %.0f MB, Usado: %.0f MB',
16, 1, @pct_used, @total_mb, @used_mb
);
-- Opcional: enviar e-mail via Database Mail
-- EXEC msdb.dbo.sp_send_dbmail ...
ENDEste job, combinado com um alerta configurado no SQL Server Agent ou no DBSnoop, garante que o time de DBA seja notificado antes que o tempdb chegue ao limite — não depois.
Seu ambiente tem monitoramento proativo do tempdb?
O serviço de DBA Remoto da HTI inclui monitoramento contínuo do tempdb via NOC 24/7, com alertas configurados por threshold e resposta proativa antes que o espaço esgote. Além do tempdb, monitoramos disponibilidade, performance, replicação e comportamentos anômalos em tempo real.
→ Conhecer o DBA Remoto da HTI06
TABELAS TEMPORÁRIAS VS. VARIÁVEIS DE TABELA: O QUE USA MAIS TEMPDB?
Esta é uma das dúvidas mais comuns de desenvolvedores que trabalham com SQL Server. A resposta curta: depende — mas há diferenças importantes que afetam tanto o uso do tempdb quanto a performance.
Tabelas temporárias (#temp)
São objetos físicos no tempdb, com estatísticas próprias. O otimizador de queries consegue usar essas estatísticas para gerar planos melhores. São ideais para grandes volumes de dados e operações complexas. O custo: são mais pesadas de criar e dropar, e persistem no tempdb enquanto a sessão está ativa.
Variáveis de tabela (@table)
Não criam estatísticas. O otimizador assume que a variável tem 1 linha — o que pode gerar planos péssimos quando ela tem milhões de linhas. São mais leves para volumes pequenos (até algumas centenas de linhas). São descartadas automaticamente ao sair do escopo — sem precisar de DROP TABLE explícito.
Table-Valued Parameters e CTEs
CTEs (Common Table Expressions) não criam objetos físicos no tempdb — são expansões de query em memória. Mas CTEs recursivos ou muito grandes podem causar spills para o tempdb via internal objects. Table-Valued Parameters se comportam como variáveis de tabela em termos de estatísticas.
"A regra prática: use @table_variable para menos de 100 linhas. Use #temp_table para qualquer coisa maior. E monitore os dois em produção."
Checklist: configuração saudável do tempdb
Use como base para revisar seus ambientes SQL Server
- Número de arquivos de dados = número de CPUs lógicas (máximo 8)
- Todos os arquivos têm o mesmo tamanho inicial e o mesmo autogrowth
- Autogrowth configurado em MB fixo, não em percentual
- Tempdb em volume de disco separado dos bancos de produção
- Log de monitoramento ativo com alerta de threshold (80%)
- Version store monitorado quando RCSI está habilitado
- SQL Server Agent job de monitoramento de tempdb configurado
- Revisão periódica de stored procedures com tabelas temporárias grandes
07
QUANDO O TEMPDB CHEIO É SINTOMA DE UM PROBLEMA MAIOR
Em muitos casos, o tempdb cheio não é o problema em si — é o sintoma de algo mais profundo no ambiente. Alguns cenários que indicam que o problema vai além de uma configuração:
- →Tempdb enche regularmente, mesmo após aumentar o tamanho. Indica que há uma query ou processo com consumo estruturalmente excessivo que precisa ser otimizado — não apenas mais espaço.
- →Version store crescendo continuamente e nunca sendo limpo. Pode indicar um bug na aplicação com transações que nunca são fechadas, ou uma réplica do Availability Group que foi desconectada.
- →Múltiplos episódios de spill de queries diferentes. Indica problema de configuração de memória ou de estatísticas desatualizadas em escala — não um único culpado.
- →Episódios acontecendo apenas em janela de manutenção. DBCC CHECKDB ou rebuilds de índice mal dimensionados para o hardware disponível.
- →Crescimento explosivo sem query óbvia responsável. Pode ser um trigger em tabela de alta escrita, uma funcionalidade de auditoria gerando versioning excessivo, ou uma aplicação com bug de transação.
Nesses casos, o diagnóstico correto requer acesso às DMVs em tempo real durante o episódio, análise de planos de execução e histórico de uso — não apenas uma query de diagnóstico pontual. É o tipo de trabalho que um DBA sênior com experiência em SQL Server de produção resolve em horas, e que pode levar dias sem esse contexto.
TEMPDB CHEIO AGORA
SQL Server parado por tempdb cheio?
Nossa Equipe de Pronta Resposta atende emergências de SQL Server 24 horas por dia. Tempdb cheio, SQL Server travado, queries falhando — SLA de 30 minutos em horário comercial, 2 horas fora dele. Sem contrato prévio.
Acionar suporte emergencial →wa.me/551140636900 · +55 11 4063-6900
TEMPDB CHEIO NÃO É AZAR. É FALTA DE MONITORAMENTO.
Episódios de tempdb cheio raramente são surpresas. São eventos previsíveis que acontecem quando o ambiente não tem monitoramento adequado. Com as queries certas rodando no momento certo, o problema é identificado antes de chegar ao limite.
A resolução também é direta quando a causa é conhecida: matar a sessão problemática, expandir emergencialmente, reconfigurar o autogrowth, otimizar a query responsável pelos spills, ou identificar a transação longa que está segurando o version store.
O que transforma um evento pontual em problema crônico é não investigar a causa raiz. O tempdb foi expandido para resolver o imediato — mas a query que criava a tabela temporária gigante ainda existe, e vai criar o mesmo problema no mês seguinte, com o dobro do volume de dados.