Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como detectar e evitar o crescimento inesperado do banco de dados SQL Server TempDB


Cada instância do SQL Server contém o banco de dados do SQL Server do sistema chamado TempDB. É típico para todas as conexões de banco de dados e quase todas as consultas fazem uso do banco de dados TempDB. É como um coração para a instância do SQL Server. Praticamente, não podemos trabalhar sem o banco de dados TempDB.

Vamos ter um rápido resumo das operações nas quais o SQL Server usa o TempDB.
  • Ordenar por e Agrupar por cláusula
  • Criação de índice e reconstrução de índice online
  • O armazenamento de tabelas temporárias e variáveis ​​de tabela está no banco de dados TempDB.
  • Isolamento de instantâneo e isolamento de instantâneo confirmado de leitura
  • Comandos DBCC
  • O hash une cursores estáticos, transações de longa duração.
  • Consultas XML
  • Objetos internos criados pelo mecanismo de banco de dados do SQL Server.
  • Lojas de versões
  • Vários conjuntos de registros ativos (MARS)

Você pode ler mais sobre o TempDB neste artigo.



O SQL Server recria esse banco de dados TempDB na reinicialização do serviço do mecanismo de banco de dados. Essa reinicialização pode ser devido à reinicialização automática ou manual do SQL Service. Podemos consultar sys.databases para visualizar a data de criação do TempDB que também é um horário de inicialização do serviço de banco de dados:

SELECT create_date AS 'SQL Service Startup Time'
FROM sys.databases
WHERE name = 'tempdb';


Configurações e práticas recomendadas do banco de dados TempDB SQL Server


Às vezes, notamos um crescimento inesperado do banco de dados TempDB. O primeiro passo para evitar isso é configurá-lo de acordo com as melhores práticas. Nesta seção, vamos ver a configuração do TempDB em diferentes versões do SQL Server.



Configure o TempDB para vários arquivos DATA com crescimento uniforme


De acordo com a prática recomendada, devemos ter vários arquivos de dados com crescimento uniforme de todos os arquivos. O número de arquivos depende dos processadores lógicos.

Processadores
Número de arquivos de dados TempDB

Processadores lógicos menores ou iguais a oito
Oito

Processadores lógicos maiores que oito

Comece com oito arquivos de dados.

Aumente os arquivos de dados em múltiplos de quatro e monitore os contadores de desempenho para contenção de TempDB.

Para versões do SQL Server anteriores a 2016, não temos configuração disponível durante o processo de instalação.

Por padrão, ele cria apenas um arquivo de dados e log com as seguintes configurações:

Arquivo principal TempDB

Aumentar automaticamente o arquivo de dados em dez por cento (até que o disco esteja cheio)

Arquivo de registro TempDB

Aumentar automaticamente o arquivo de dados em dez por cento (até que o disco esteja cheio ou o tamanho máximo do arquivo de log atinja 2 TB)


Configuração do banco de dados SQL Server 2014 TempDB SQL Server






O SQL Server 2016 fornece aprimoramentos para a configuração do TempDB durante o processo de instalação de acordo com a prática recomendada:

Arquivos primários e secundários do TempDB

Crescimento automático de 64 MB (até que o disco esteja cheio)

Arquivo de registro TempDB

Aumento automático de 64 MB (até que o disco esteja cheio ou o tamanho máximo do arquivo de log atinja 2 TB)


Configuração do SQL Server 2016 em diante TempDB





Banco de dados SQL Server de crescimento automático desigual TempDB


O SQL Server usa um método round-robin para preencher vários arquivos de dados se eles não tiverem o mesmo tamanho. Às vezes, vemos que um arquivo fica enorme, mas outros arquivos permanecem com crescimento mínimo. No caso de arquivos irregulares, o SQL Server usa o arquivo maior para a maioria das consultas e continuaria crescendo:
  1. Use o mesmo crescimento automático de arquivos TempDB (conforme discutido no ponto anterior).
  2. Ative o sinalizador de rastreamento 1117 para aumentar todos os arquivos de dados juntos em um banco de dados.

O segundo ponto é corrigido automaticamente no SQL Server 2016 em diante, mas você deve habilitá-lo em versões anteriores. Não exigimos esse sinalizador de rastreamento no SQL Server 2016 e superior.

Cenários de crescimento do TempDB


Nesta seção, veremos alguns cenários para o crescimento do TempDB do banco de dados SQL Server. Na minha instância SQL, tenho oito arquivos de dados com a seguinte configuração:



Agora, execute a seguinte consulta para criar uma tabela temporária e realizar a inserção de dados. O local de armazenamento de tabela temporária é o banco de dados TempDB. Essa consulta usa um operador CROSS JOIN com várias colunas e classifica ainda mais os resultados usando a cláusula ORDER BY.

Observação: Não execute esta consulta no sistema de produção; Estou usando-o apenas para fins de demonstração.

SELECT *
FROM sys.configurations
CROSS JOIN sys.configurations SCA
CROSS JOIN sys.configurations SCB
CROSS JOIN sys.configurations SCC
CROSS JOIN sys.configurations SCD
CROSS JOIN sys.configurations SCE
CROSS JOIN sys.configurations SCF
CROSS JOIN sys.configurations SCG
CROSS JOIN sys.configurations SCH
ORDER BY SCA.name,
SCA.value,
SCC.value_in_use DESC;


Essa consulta levará muito tempo e poderá resultar em alto uso da CPU também em seu sistema. Enquanto a consulta estiver em execução, abra outra janela de consulta e use o DMV sys.dm_db_task_space_usage para obter informações de alocação de página e atividade de desalocação pela tarefa. Unimos este DMV com outros DMV's para obter as informações necessárias para o banco de dados SQL Server TempDB:

SELECT s.session_id, dbu.database_id
, dbu.internal_objects_alloc_page_count, dbu.internal_objects_dealloc_page_count
, (dbu.internal_objects_alloc_page_count - dbu.internal_objects_dealloc_page_count) * 8192 / 1024 kbytes_used_internal
, r.total_elapsed_time
FROM sys.dm_Exec_requests r
INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
LEFT JOIN sys.dm_db_task_space_usage dbu ON dbu.session_id = r.session_id
AND dbu.request_id = r.request_id
WHERE internal_objects_alloc_page_count > 0
ORDER BY kbytes_used_internal DESC;
Na saída, vemos as contagens de páginas de objetos internos e seus tamanhos (kbytes_used_internal) para o ID de sessão 55. Otimizador de consulta do SQL Server executando essa consulta em um modelo paralelo; portanto, podemos ver vários IDs de sessão 71 na saída:



Você também pode visualizar o plano de execução estimado e, conforme mostrado abaixo, obtemos dois operadores caros:
  • Paralelismo:47,3%
  • Classificação:52,3%



No operador de classificação, podemos ver o alto custo estimado do operador 138.576,5:



A consulta a seguir usa DMV sys.dm_db_file_space_usage e une-o com sys.master_files para verificar as contagens de páginas de extensão alocadas e não alocadas no banco de dados TempDB do SQL Server enquanto a consulta está em execução:

select mf.physical_name, mf.size as entire_file_page_count,
dfsu.unallocated_extent_page_count,
dfsu.user_object_reserved_page_count,
dfsu.internal_object_reserved_page_count,
dfsu.mixed_extent_page_count
from sys.dm_db_file_space_usage dfsu
join sys.master_files as mf
on mf.database_id = dfsu.database_id
and mf.file_id = dfsu.file_id


Podemos monitorar a execução da consulta, seu uso no banco de dados TempDB e, se necessário, matar o processo para liberar o espaço imediatamente. Também devemos otimizar a consulta causando um crescimento maciço do TempDB.


Monitore o uso do TempDB do banco de dados SQL Server usando eventos estendidos


Eventos estendidos são úteis para monitoramento de banco de dados TempDB. Podemos adicionar os seguintes eventos estendidos usando a consulta:
  • database_file_size_change
  • databases_log_file_used_size_changed

Criar evento estendido


CREATE EVENT SESSION [TempDB Usage] ON SERVER
ADD EVENT sqlserver.database_file_size_change(

ACTION(sqlserver.client_hostname,sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text)),
ADD EVENT sqlserver.databases_log_file_used_size_changed(

ACTION(sqlserver.client_hostname,sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text))
ADD TARGET package0.event_file(SET filename=N'TempDBUsage',max_rollover_files=(0))
WITH (STARTUP_STATE=OFF)
GO

Iniciar sessão de evento estendida


ALTER EVENT SESSION [TempDBTest] ON SERVER STATE = START;

Agora, execute sua carga de trabalho para usar o banco de dados TempDB e aumentar os arquivos de dados. Os eventos estendidos capturam o crescimento do arquivo de dados e a consulta que causou esse crescimento.

Você pode visualizar o arquivo de sessão de evento estendido no modo SSMS GUI ou usar a consulta a seguir para monitorar o crescimento do TempDB.


Monitorar o crescimento do TempDB


SELECT [eventdata].[event_data].[value]('(event/action[@name="session_id"]/value)[1]', 'INT') AS [SessionID],
[eventdata].[event_data].[value]('(event/action[@name="client_hostname"]/value)[1]', 'VARCHAR(100)') AS [ClientHostName],
DB_NAME([eventdata].[event_data].[value]('(event/action[@name="database_id"]/value)[1]', 'BIGINT')) AS [GrowthDB],
[eventdata].[event_data].[value]('(event/data[@name="file_name"]/value)[1]', 'VARCHAR(200)') AS [GrowthFile],
[eventdata].[event_data].[value]('(event/data[@name="file_type"]/text)[1]', 'VARCHAR(200)') AS [DBFileType],
[eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(MAX)') AS [EventName],
[eventdata].[event_data].[value]('(event/data[@name="size_change_kb"]/value)[1]', 'BIGINT') AS [SizeChangedKb],
[eventdata].[event_data].[value]('(event/data[@name="total_size_kb"]/value)[1]', 'BIGINT') AS [TotalSizeKb],
[eventdata].[event_data].[value]('(event/data[@name="duration"]/value)[1]', 'BIGINT') AS [DurationInMS],
[eventdata].[event_data].[value]('(event/@timestamp)[1]', 'VARCHAR(MAX)') AS [GrowthTime],
[eventdata].[event_data].[value]('(event/action[@name="sql_text"]/value)[1]', 'VARCHAR(MAX)') AS [QueryText]
FROM
(
SELECT CAST([event_data] AS XML) AS [TargetData]
FROM [sys].[fn_xe_file_target_read_file]('C:\TEMP\TempDBusage*.xel', NULL, NULL, NULL)
) AS [eventdata]([event_data])
WHERE [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(100)') = 'database_file_size_change'
OR [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(100)') = 'databases_log_file_used_size_changed'
AND [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(MAX)') <> 'databases_log_file_used_size_changed'
ORDER BY [GrowthTime] ASC;



Isolamento de instantâneo


Você pode usar o isolamento de instantâneo para suas consultas. Nesse modelo de isolamento, o SQL Server armazena as versões de linha atualizadas de cada transação no TempDB. No caso de uma transação grande ou de longa duração, você pode ver um enorme banco de dados TempDB.

Você pode executar a transação com o comando SET e especificar o isolamento do Snapshot:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRAN;
UPDATE [AdventureWorks].[Person].[Person]
SET
[Title] = 'Mr.';
COMMIT TRAN;


Você também pode consultar sys.databases visualização do sistema para verificar se algum banco de dados do usuário tem isolamento de instantâneo.

Consulta para habilitar o isolamento de instantâneo no banco de dados AdventureWorks


ALTER DATABASE AdventureWorks
SET ALLOW_SNAPSHOT_ISOLATION ON
GO

Consulta para verificar o banco de dados do usuário com isolamento de instantâneo


SELECT *
FROM sys.databases
WHERE(snapshot_isolation_state = 1
OR is_read_committed_snapshot_on = 1)
AND database_id > 4;


Na captura de tela a seguir, você pode ver que o banco de dados AdventureWorks tem isolamento de instantâneo. O banco de dados TempDB também possui isolamento de instantâneo, mas na consulta, ignoramos database_id menor que 4:





Podemos usar o DMV sys.dm_db_file_space_usage para monitorar o armazenamento de versão no TempDB:

SELECT GETDATE() AS runtime,
SUM(user_object_reserved_page_count) * 8 AS usr_obj_kb,
SUM(internal_object_reserved_page_count) * 8 AS internal_obj_kb,
SUM(version_store_reserved_page_count) * 8 AS version_store_kb,
SUM(unallocated_extent_page_count) * 8 AS freespace_kb,
SUM(mixed_extent_page_count) * 8 AS mixedextent_kb
FROM sys.dm_db_file_space_usage;


Aqui, podemos ver que o tamanho do armazenamento de versão é 67968 KB. Para uma transação grande ou de longa duração, você pode ver um tamanho enorme de TempDB do banco de dados SQL Server devido a este armazenamento de versão:



Outro caso que pode causar um grande tamanho do armazenamento de versão é Sempre na réplica secundária somente leitura. Se você executar qualquer consulta no banco de dados secundário, ele usará automaticamente o nível de isolamento de instantâneo. Como você sabe, o nível de isolamento de instantâneo copia a versão da linha no TempDB.

Você deve monitorar os seguintes contadores de perfmon:
  • SQLServer:Transactions\Longest Transaction Running Time – Ele captura a transação ativa mais estendida.
  • SQLServer:Transactions\Version Store Size (KB) – Captura o tamanho atual de todas as versões armazenadas no TempDB.
  • SQLServer:Transactions\Version Cleanup rate (KB/s) ) – Você pode usar este contador para mostrar a taxa de limpeza de versão no TempDB
  • SQLServer:Transações\Taxa de geração de versão (KB/s) – Você pode capturar a taxa de captura do armazenamento de versão usando este contador.

Você também deve monitorar o crescimento do TempDB para o controle de versão em Sempre no banco de dados secundário. Mate as sessões de longa duração para que possa limpar o controle de versão e recuperar espaço no banco de dados TempDB.

Conclusão


Neste artigo, aprendemos sobre a prática recomendada do banco de dados TempDB do banco de dados SQL Server e os diferentes métodos para detectar e evitar o crescimento inesperado. Você deve monitorar o TempDB regularmente e configurar alertas diferentes para ser proativo.
  • Monitoramento de tamanho do TempDB
  • Monitoramento do espaço no drive
  • Transações de longa duração