Há um persistente mito no SQL Server mundo de que tanto o DROP TABLE
e TRUNCATE TABLE
comandos não são registrados.não são. Estão ambos totalmente registados, mas eficientemente registados.pode facilmente provar isso a si próprio., Execute o código a seguir para configurar um banco de dados de teste e a tabela, e mostrar que nós temos 10.000 linhas na nossa tabela:
Resultados:
—-
10000
E, em seguida, o código a seguir, que trunca a tabela em uma transação e verifica a contagem de linha:
BEGIN TRAN;GOTRUNCATE TABLE ;GO SELECT COUNT (*) AS N'RowCount'FROM ;GO
Resultados:
—-
0
Agora que a tabela está vazia., Mas eu posso reverter a transacção e todos os dados novamente:
ROLLBACK TRAN;GO SELECT COUNT (*) AS N'RowCount'FROM ;GO
Resultados:
—-
10000
Claramente o TRUNCATE
operação deve ser registada de outra forma a reverter a operação não iria funcionar.de onde vem o equívoco?
se trata do comportamento de DROP
e TRUNCATE
operações em tabelas grandes., Eles irão completar quase instantaneamente, e se você olhar no diário de transações usando fn_dblog
logo depois, você verá apenas um pequeno número de registros de log gerados a partir da operação. Esse pequeno número não está correlacionado com o tamanho da tabela sendo truncada ou descartada, então parece que as operações e TRUNCATE
são não registradas.mas estão completamente registados, como demonstrei acima. Onde estão os registos das operações?,
a resposta é que os registros de log serão criados, mas não imediatamente, por um mecanismo chamado ‘drop diferido’, que foi adicionado no SQL Server 2000 SP3.
Quando uma tabela é descartada ou truncada, todas as páginas do arquivo de dados alocados para a tabela devem ser desalocadas.,uire um exclusivo de atribuição de bloqueio na extensão
Sonda o bloqueio de página para cada página na extensão (adquirir o bloqueio no modo exclusivo, e imediatamente solte-o, certificando-se de que ninguém mais tem a página bloqueada)
NÃO liberar o bloqueio de extensão, garantindo que ninguém mais pode usar a extensão
Mover para a próxima extensão
Fim
Como todos os bloqueios de extensão foram realizadas até o final da operação, e cada bloqueio leva uma pequena quantidade de memória, foi possível para o gestor de bloqueio para ser executado fora da memória quando um DROP
ou TRUNCATE
de uma tabela muito grande ocorreu., Alguns clientes de servidores SQL começaram a descobrir que eles correram em condições de falta de memória no SQL Server 2000, como tabelas cresceram muito grandes e superaram o crescimento da memória do sistema.
O diferidos-drop mecanismo simula DROP
ou TRUNCATE
operação de concluir imediatamente, por desengatar as atribuições para a mesa e colocá-los em ‘diferidos-queda de fila”, para processamento posterior por uma tarefa de plano de fundo. Esta operação de desaperto e transferência só gera um punhado de registos., Esta é a operação que está sendo feita e rolada de volta no meu exemplo de código acima.
a ‘tarefa de fundo diferido-drop’ gira a cada poucos segundos e desaloca todas as páginas e extende na fila de largada diferida em pequenos lotes, garantindo que a operação não ficará sem memória. Estes deallocations são todos totalmente conectado, mas lembre-se que anular uma página cheia de dados ou de índice de registros de não fazer indivíduo exclui os registros; em vez disso, a página inteira é apenas marcado como desalocado no respectivo PFS (Espaço Livre de Página) de alocação de byte-mapa.,
a Partir do SQL Server 2000 SP3 em diante, quando você executar um DROP
ou TRUNCATE
de uma tabela, você verá apenas alguns registros de log que está sendo gerado. Se você esperar um minuto ou assim, e então olhar no log de transação novamente, você verá milhares de registros de log foram gerados pela operação de entrega diferida, cada um descalocando uma página ou extensão. A operação é completa e eficientemente registrada.,
Aqui está um exemplo, usando o cenário que criamos acima:
CHECKPOINT;GOTRUNCATE TABLE ;GOSELECT COUNT (*) AS N'LogRecCount'FROM fn_dblog (NULL, NULL);GO
Resultados:
—-
25
Como você pode ver, há claramente não são registros de log de anular as 10.000 páginas, mais de 1.250 extensões na tabela TestTable.se eu esperar alguns segundos, e então executar o id
code again, I get:
—-
3811
You might wonder why there aren’t at least 10,000 log records – one for each page being deallocated., Isso porque as chamadas de páginas são registradas de forma eficiente – com um registro de registro refletindo mudanças de alocação de páginas PFS para 8 páginas de arquivos de dados consecutivos, em vez de um registro de cada página de arquivo de dados refletindo seu estado de alocação mudando na página PFS.
SQL Server sempre tenta produzir o menor log de transação possível, enquanto ainda adere às regras sobre o registro completo ou mínimo com base no modelo de recuperação atual., Se quiser ver os registos de Registo reais gerados pelos mecanismos de desbloqueamento e transferência diferida, basta substituir * pela contagem (*) no código FN_ dblog acima e procurar uma transacção com o nome da transacção definido para DeferredAllocUnitDrop::Process
.
em posts futuros vou discutir os internos que sustentam outros mitos persistentes em torno de aspectos de desempenho do motor de armazenamento do servidor SQL.
Deixe uma resposta