Cada banco de dados do SQL Server contém um ou mais arquivos de log de transações além dos arquivos de dados. Os arquivos de log registram todas as transações e modificações no banco de dados feitas por cada um deles.
Este artigo se concentra no log de transações e em como o SQL Server registra as modificações de dados para usar os dados para a recuperação de falha do banco de dados.
Introdução ao arquivo de log de transações do SQL Server
Como lembramos, cada transação é “tudo ou nada”. Se uma parte da transação falhar, toda a transação falhará e o estado do banco de dados permanecerá inalterado.
O SQL Server armazena um registro de cada transação realizada no banco de dados no arquivo de log. Se algum desastre acarretar o desligamento do SQL Server, ele usa um log de transações para recuperar o banco de dados para um estado consistente com integridade de dados.
Após a reinicialização, o SQL Server inicia o processo de recuperação de falhas. Ele lê o arquivo de log de transações para garantir que todos os dados válidos sejam armazenados nos arquivos de dados e que as transações não confirmadas sejam revertidas.
Durante a operação normal, o SQL Server também usa o log de transações. As informações contidas no arquivo são necessárias para identificar o que o SQL Server precisa fazer quando uma transação é revertida devido a um erro ou a uma instrução ROLLBACK especificada pelo usuário.
Como o SQL Server usa o log de transações
O log de transações é um arquivo físico com a extensão LDF . O SQL Server o cria automaticamente para qualquer novo banco de dados junto com o arquivo de dados primário (.MDF ) que armazena os objetos do banco de dados e os próprios dados.
Sempre que o código T-SQL altera um objeto de banco de dados ou os dados que ele contém, os detalhes da alteração são registrados como um registro de log no arquivo de log de transações.
O registro de log contém as informações de uma alteração específica feita no banco de dados (por exemplo, inserir uma única linha). Portanto, teremos uma série de registros de log para descrever completamente os efeitos de uma única transação.
Arquitetura do log de transações
Números de sequência de log
Um registro de log tem um número de sequência de log exclusivo e com incremento automático (LSN ), que nos permite encontrar esse registro no log de transações. LSN descreve a alteração de dados e contém as seguintes informações:
- a operação e a linha afetada
- as versões antigas e novas dos dados
- a transação que realizou a modificação
LSN é composto por três números:
LSN =
Cada página de arquivo de dados tem um LSN em seu cabeçalho de página que identifica o registro de log mais recente cuja alteração é refletida na página. Isso é crítico para a recuperação de falhas.
Quando a recuperação de falhas é executada, ela compara os LSNs dos registros de log para transações confirmadas ou não confirmadas com os LSNs nas páginas do arquivo de dados para determinar se há algum refazer ou desfazer a ser feito nesses registros de log específicos.
Ao criar um banco de dados, uma boa prática é especificar o tamanho do log de transações . Se você não fizer isso, o SQL Server criará automaticamente o log de transações com o tamanho padrão.
O tamanho padrão do log de transações de um novo banco de dados é o maior de 0,5 MB ou 25% do tamanho total de todos os arquivos de dados criados na mesma instrução CREATE DATABASE.
Você precisa ter muito cuidado porque novas partes do log de transações são sempre inicializadas com zero . Se você tiver a instrução CREATE DATABASE sem especificar o tamanho do arquivo de log e criar, por exemplo, um banco de dados de 1 TB, o SQL Server criará o log de transações de 250 GB.
Como o log deve ser inicializado com zero, ele não faz uso da inicialização instantânea do arquivo. Esse recurso foi adicionado no SQL Server 2005 para permitir que os arquivos de dados sejam criados ou aumentados quase instantaneamente.
Podemos ver o que está acontecendo quando CREATE DATABASE – a inicialização zero ocorre do nosso log usando trace flag 3004 que imprime mensagens sobre inicialização zero e sinalizador de rastreamento 3605 que permite imprimir essas mensagens de log pelo sinalizador de rastreamento 3004.
A demonstração a seguir mostra como você pode ver a zeragem do arquivo de log acontecendo.
1. Execute o script a seguir para garantir que não tenhamos um banco de dados chamado DBTest2014
USE master;
GO
IF DATABASEPROPERTY(N'DBTest2014', N'Version')>0
BEGIN
ALTER DATABASE DBTest2014 SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
DROP DATABASE DBTest2014;
END
GO
2. Ative os sinalizadores de rastreamento para observar a inicialização zero
DBCC TRACEON (3605, 3004, -1);
GO
3. Flush the error log
EXEC sp_cycle_errorlog;
GO
3. Crie um banco de dados
CREATE DATABASE DBTest2014 ON PRIMARY (
NAME = N'DBTest2014',
FILENAME = N'D:\DBTest2014_data.mdf')
LOG ON (
NAME= N'DBTest2014_log',
FILENAME= N'D:\DBTest2014_log.ldf',
SIZE = 10MB,
FILEGROWTH = 10 MB);
GO
4. Leia o arquivo de log de erros
EXEC sys.xp_readerrorlog;
GO
Arquivos de registro virtuais
O log de transações é dividido internamente em uma série de partes chamadas arquivos de log virtuais (VLFs ) para simplificar a gestão.
Sempre que um log de transações é criado, ele fornece um certo número de VLFs. Os VLFs recém-criados são inativos e não utilizados. Um VLF ativo não pode ser reutilizado até que seja inativo pela limpeza do log.
No entanto, há uma exceção – o primeiro VLF em um novo banco de dados está sempre ativo porque qualquer log de transações deve ter pelo menos um VLF ativo.
Cada arquivo de registro também tem uma página de cabeçalho de arquivo que leva 8 KB no início do arquivo de log de transações. A página de cabeçalho do arquivo armazena metadados sobre o arquivo, como configurações de tamanho e crescimento automático.
O número e o tamanho dos VLFs em uma nova parte do log de transações são determinados pelo SQL Server. É impossível configurá-lo.
Se o tamanho recém-adicionado for:
- <1 MB é irrelevante para discussão
- <64 MB, haverá 4 novos VLFs (cada 1/4 do tamanho de crescimento)
- 64 MB a 1 GB, haverá 8 novos VLFs (cada 1/8 do tamanho de crescimento)
- > 1 GB, haverá 16 novos VLFs (cada 1/16 do tamanho de crescimento)
Isso se aplica ao log de transações criado inicialmente e a cada crescimento manual ou automático que ocorrer. Quando você conhece a fórmula do número potencial de VLFs e seu tamanho potencial, ajuda a gerenciar o log. Poucos ou muitos VLFs podem causar problemas de desempenho com operações de log de transações.
Número de sequência VLF
Cada VLF tem um número de sequência para identificar exclusivamente o VLF no log de transações. O número de sequência aumenta em um toda vez que o sistema de gerenciamento de log ativa o próximo VLF. A cadeia dos números de sequência fornece o conjunto de VLFs atualmente ativo.
O início da parte ativa do log de transações começa com um VLF que possui o número de sequência mais baixo e ainda está ativo. Os VLFs inativos têm números de sequência, mas não fazem parte da parte ativa do log.
A parte ativa do log possui registros de log que são exigidos por algum motivo pelo SQL Server.
Quando você cria um novo banco de dados pela primeira vez, os números de sequência VLF não começam em 1. Eles começam com o número de sequência VLF mais alto no log de transações do banco de dados modelo, mais 1 . É impossível ficar sem números de sequência VLF. O SQL Server tem um código que forçará o desligamento da instância se um número de sequência de VLF chegar a zero (se o próximo número de sequência de VLF for menor que o anterior).
VLF e blocos de registro
Dentro de VLFs, existem blocos de log de tamanho variável. O tamanho mínimo do bloco de log é 512 bytes e blocos de log crescem até um tamanho máximo de 60 KB . O tamanho é definido quando ocorre um dos seguintes casos:
- Uma transação gera um registro de log para confirmar a conclusão de abortar uma transação
- O tamanho do bloco de log atinge 60 KB sem que uma transação seja confirmada ou anulada
Existem registros de log dentro de um bloco de log (colorido no diagrama). Os registros de log também são de tamanho variável. O diagrama mostra que os registros de log de várias transações simultâneas podem existir no mesmo bloco de log. Os registros de log são armazenados na ordem escrita de forma semelhante a um arquivo de página de dados.
Cada VLF contém um cabeçalho VLF com as seguintes informações:
- Se o VLF está ativo ou não.
- O número de sequência de log quando o VLF foi criado.
- Os bits de paridade atuais para todos os blocos de 512 bytes no VLF.
Os bits de paridade começam em 64 pela primeira vez de uso VLF. Se o VLF ficar inativo, mas for reativado, os bits de paridade se tornarão 128. Eles são usados durante a recuperação de falhas.
Examinando detalhes do log de transações – DBCC LOGINFO
A única maneira de ver a estrutura do log de transações é usar o DBCC LOGINFO não documentado comando. A sintaxe do comando é:
DBCC LOGINFO [({'dbname | dbid'})]
Se você não especificar dbname e dbid , ele despejará o conteúdo do log do banco de dados atual.
O resultado é uma linha para cada VLF que está no log de transações desse banco de dados. Os campos retornados são:
- RecoveryUnitId — adicionado no SQL Server 2012, mas atualmente não utilizado
- FileId — ID do arquivo de log de transações em um banco de dados.
- Tamanho do arquivo — Tamanho do VLF em bytes.
- StartOffset — deslocamento inicial do VLF no arquivo de log de transações, em bytes
- FSeqNo — O número de sequência VLF
- Estado — Se o VLF está ativo ou não (0 =inativo, 2 =ativo, 1 – não é usado)
- Paridade — bits de paridade atuais (64 ou 128, ou 0 se o VLF nunca esteve ativo)
- CriarLSN — o LSN quando o VLF foi criado (0 =o VLF foi criado quando o arquivo de log de transações foi criado inicialmente). Todos os outros VLFs adicionados após a criação inicial do arquivo de log de transações terão CreateLSN diferente de zero.
Podemos executar o seguinte comando para o DBTest2014 banco de dados, que criamos anteriormente:
DBCC LOGINFO (N'DBTest2014');
GO
Veja o resultado:
DBCC SQLPERF (LOGSPACE)
A única maneira no Transact-SQL para examinar a quantidade de log usada é DBCC SQLPERF. A sintaxe do comando é:
DBCC SQLPERF
(
[ LOGSPACE ]
|
[ "sys.dm_os_latch_stats" , CLEAR ]
|
[ "sys.dm_os_wait_stats" , CLEAR ]
)
[WITH NO_INFOMSGS ]
O comando retorna um conjunto de resultados com uma linha por banco de dados:
- Nome do banco de dados
- Tamanho do registro (MB)
- Espaço de log usado (%)
- Status:sempre definido como zero
No meu ambiente, o seguinte comando:
DBCC SQLPERF (LOGSPACE);
GO
Retorna o seguinte resultado:
No próximo artigo, examinaremos os registros de log.