Este é o segundo artigo da série dedicado ao log de transações do SQL Server e suas especificidades. Aqui vamos examinar os detalhes do registro de log.
Registros de Log
Os registros de log são o núcleo dos mecanismos de log e recuperação. Um registro de log descreve uma única alteração em um banco de dados. Assim, cada alteração em um banco de dados possui um registro de log ou registros de log que ajudam a descrever essa alteração específica. Embora você não precise entender os detalhes do registro de log, para entender o que está acontecendo com o log e a recuperação, esses detalhes são extremamente interessantes.
O registro de log possui um número de sequência de log exclusivo que definimos no primeiro artigo. O Número de Sequência de Log permite que o registro de log seja encontrado no log de transações. Além disso, 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.
Registros de log para transações simultâneas são misturados no log de transações de acordo com o momento em que ocorreram. Os registros de log são armazenados em blocos de log no buffer pool até que sejam liberados para o disco.
Não há operações não registradas nos bancos de dados do usuário ou do sistema. No entanto, há uma exceção:no tempdb, as operações de armazenamento de versão e arquivo de trabalho não são registradas. Os registros de log nunca são movidos no log de transações.
O que está dentro de um registro de log?
As informações em um registro de log permitem que ele seja refeito (avançado) ou desfeito (revertido). Essa capacidade de um registro de log é crucial para permitir que as transações sejam revertidas e para o trabalho de recuperação. Os registros de log contêm muitos campos, dependendo do tipo de registro de log. Existem alguns campos comuns entre todos os registros, incluindo:
- O tipo de registro de registro
- iniciar registro de log de transações
- confirmar registro de log de transações
- alocando uma página alterando o bitmap de alocação
- inserindo uma linha
- excluindo uma linha
- modificar uma linha
- O contexto do registro , se houver.
- O ID da transação do qual o registro de log faz parte caso existam. A maioria dos registros de log faz parte das transações.
- O comprimento do registro de log . Os registros de log geralmente têm um tamanho fixo e, dependendo da quantidade de dados que estão no registro de log, haverá uma parte variável também.
- O LSN do registro de log anterior na mesma transação . Caso existam. O LSN é essencialmente um ponteiro para o registro de log de transações anterior que foi gerado por essa transação específica. Essa cadeia de LSNs anteriores permite que essa transação específica seja revertida, porque a reversão é feita na ordem inversa, começando no registro de log mais recente.
- A quantidade de espaço de log reservado caso o registro de log precise ser desfeito.
Reserva de espaço de log
Cada registro de log gerado na parte de encaminhamento de uma transação deve reservar espaço livre no log de transações para permitir que o registro de log seja revertido, sem que o log de transações precise crescer.
O mecanismo de reserva de espaço de log é muito conservador, sempre reservando espaço suficiente, e geralmente mais, caso ocorra uma situação inesperada. Por exemplo, uma atualização ou exclusão em uma tabela compactada reservará mais espaço do que uma atualização ou exclusão semelhante em uma tabela não compactada. Isso acontece porque a reversão da atualização na tabela compactada pode ter que lidar com a linha atualizada que não está mais em uma página compactada e, portanto, teria que gravar colunas de largura total no registro de log em vez de dados compactados.
Tipos de registro de log
Existem muitos tipos de registros de log, incluindo:
- LOP_FORMAT_PAGE A operação da página de formato de log — é onde uma página foi formatada, o que significa que seu cabeçalho foi criado. O registro de log registrará pelo menos o cabeçalho da página e potencialmente mais algum conteúdo da página se a página tiver sido criada e preenchida como parte de uma operação como uma compilação ou reconstrução de índice)
- LOP_MODIFY_ROW Esta operação está alterando uma pequena parte de um dado existente.
- LOP_SET_BITS Este registro de log se aplica a bitmaps de alocação.
- LOP_INSERT_ROWS e LOP_DELETE_ROWS
- LOP_SET_FREE_SPACE Aplica-se ao PFS – a alocação do bitmap que acompanha os status de alocação das páginas.
Quaisquer registros de log que farão uma alteração em uma página de dados ou em uma página de índice em um índice tabular incluem :
- O ID da unidade de alocação
- O ID da página e o ID do slot do registro na página, que é essencialmente o ID do registro com base em zero dos dados ou do registro de índice na página.
- A imagem posterior ou a imagem anterior e a imagem posterior dos dados alterados. Pode haver vários conjuntos deles em um único registro de log. As pós-imagens permitem que o refazer ocorra. As imagens anteriores permitem que o desfazer ocorra.
Bloquear registro
Alguns registros de log incluem um bitmap de quais bloqueios foram mantidos quando a alteração descrita ocorreu. O bitmap contém:
- Contagem do número de bloqueios.
- Que tipo e modo de bloqueio – por exemplo, um bloqueio de página no modo X.
- Qual é o bloqueio
Durante a recuperação de falhas e os failovers do grupo de disponibilidade/espelhamento de banco de dados, esses bloqueios serão adquiridos para todos os registros de log que serão desfeitos. Isso permite o recurso de recuperação rápida no Enterprise Edition do SQL Server 2005 em diante.
Registros de log em transações
Todas as transações geram pelo menos três registros de log, sempre na seguinte sequência:
- LOP_BEGIN_XACT – inclui informações como SPID, nome da transação e hora de início. Todas as transações iniciadas pelo SQL Server têm nomes para descrever a operação (por exemplo, AllocFirstPage, DROPOBJ)
- Outros registros da transação.
- LOP_COMMIT_XACT – se a transação for confirmada.
- LOP_ABORT_XACT – se a transação for revertida.
Ambos incluem a hora de término da transação.
Os registros de log em uma transação são vinculados por LSN. Isso significa que o próximo registro de log gerado para uma transação tem o LSN do registro de log anterior que foi gerado para essa transação específica. Isso permite que a transação seja revertida corretamente. Alguns registros de log não são transacionais, incluindo:
- Alterações de espaço livre do PFS (impossível reconciliar com outras transações)
- Mudanças diferenciais de bitmap (somente alteração unidirecional)
Examinando registros de log
Há duas maneiras de examinar os registros de log. Você pode usar a função DBCC LOGINFO, mas é recomendável usar a função com valor de tabela fn_dblog. Tem uma sintaxe extremamente simples:
SELECT * FROM fn_dblog (startLSN, endLSN); GO
É uma função extremamente poderosa porque:
- retorna um conjunto de resultados tabular que pode ser facilmente gerenciado.
- permite que predicados complexos sejam usados.
- verifica todo o log de transações na parte ativa do log, desde o início da transação não confirmada mais antiga até o registro de log mais recente. Isso pode ser substituído usando o sinalizador de rastreamento 2537
Os campos startLSN e endLSN geralmente são passados como NULL
Aqui está a demonstração:
USE DBTest2014 GO SET NOCOUNT ON; GO --Set the SIMPLE recovery mode with no auto-stats -- to avoid unwanted log records ALTER DATABASE DBTest2014 SET RECOVERY SIMPLE; ALTER DATABASE DBTest2014 SET AUTO_CREATE_STATISTICS OFF; CREATE TABLE [TEST_TABLE] ([C1] INT, [C2] INT, [C3] INT); INSERT INTO [TEST_TABLE] VALUES (1,1,1); GO --Clear out the log CHECKPOINT; GO -- Implicit transaction INSERT INTO [TEST_TABLE] VALUES (2,2,2); GO SELECT * FROM fn_dblog(null, null); GO
Aqui está o conjunto de resultados reduzido. Na verdade, fn_dblog retorna uma variedade de registros diferentes, como Comprimento do registro de log, Bits de sinalização, Reserva de log, AllocUnitId, PageID, SlotID, LSN da página anterior e outros.
Modificando o conteúdo da linha
As modificações de registro são registradas de duas maneiras:como LOP_MODIFY_ROW ou LOP_MODIFY_COLUMNS registro. Não importa qual método é usado, ele registrará os bytes que estão realmente sendo alterados. Por exemplo, alterar um valor INT de 1 para 24 registra apenas um byte de alteração, pois os outros três zero bytes não foram alterados. O SQL Server usará um LOP_MODIFY_ROW registro de log se houver uma única parte da linha sendo atualizada. Uma porção é definida da seguinte forma:cada coluna de comprimento variável na linha é uma “porção” e toda a área de largura fixa da linha é uma “porção”, mesmo se várias colunas estiverem sendo atualizadas, mas somente se os bytes estiverem sendo atualizados estão separados por 16 bytes ou menos na linha.
LOP_MODIFY_ROW contém:
- Antes da imagem
- Após a imagem
- Colunas de chave de índice, se aplicável
- Bloquear bitmap
LOP_MODIFY_COLUMNS contém:
- Antes e depois da matriz de deslocamentos
- Matriz de comprimento
- Colunas de chave de índice, se aplicável
- Bloquear bitmap
- Pares de imagens antes e depois
Registros de registro de compensação
Este é um tipo especial de registros de log que são usados para ajudar na reversão de uma transação. Quando uma transação é revertida, a alteração descrita por cada registro de log na transação deve ser desfeita no banco de dados. A reversão começa com o registro de log mais recente da transação e segue os links LSN anteriores até o registro de log LOP_BEGIN_XACT. Para cada registro de log:
- Realize a “anti-operação” que anulará os efeitos do registro de log
- Gere um registro de log, marcando-o como um registro de log de COMPENSAÇÃO, pois está compensando o registro de log na parte de encaminhamento da transação.
- O LSN anterior do registro de COMPENSATION aponta para o registro de log anterior ao que está compensando. Essencialmente, faz com que o registro de log não faça mais parte da cadeia de registros de log da transação.
- O espaço de log reservado para o registro de log é liberado
Os registros de log de COMPENSAÇÃO não podem ser desfeitos, apenas refeitos.
Reversão de uma transação
Aqui está uma representação gráfica do que está acontecendo quando uma transação é revertida:
Vamos examinar o seguinte código:
USE DBTest2014 GO SET NOCOUNT ON; GO ALTER DATABASE DBTest2014 SET RECOVERY SIMPLE; ALTER DATABASE DBTest2014 SET AUTO_CREATE_STATISTICS OFF; CREATE TABLE [TEST_TABLE] ([C1] INT, [C2] INT, [C3] INT); INSERT INTO [TEST_TABLE] VALUES (1,1,1); INSERT INTO [TEST_TABLE] VALUES (2,2,2); GO --Clear out the log CHECKPOINT; GO -- Explicit transaction to insert a new record BEGIN TRAN; INSERT INTO [TEST_TABLE] VALUES (3,3,3); GO SELECT * FROM fn_dblog(null, null); GO --Roll it back ROLLBACK TRAN; GO SELECT * FROM fn_dblog(null, null);
Aqui podemos ver um registro de log especial com a descrição “COMPENSATION”
Se olharmos para o LSN anterior, podemos ver que LOP_INSERT_ROWS que fizemos, links para …0f40:0001 e esta é a transação BEGIN porque a parte de encaminhamento da transação é vinculada ao registro de log anterior. O LOP_DELETE_ROW registro de log de compensação não liga de volta a um registro que está compensando - ele liga a ele (para o registro de log de transação BEGIN).
Portanto, DELEDE compensou INSERT e o removeu da lista de registros de log. OLOP_ABORT_XACT é o sinal de que a transação foi finalizada com o rollback. Além disso, você pode ver que LOP_ABORT_XACT links para o LOP_BEGIN_XACT.
Quando fazemos um registro de log de compensação, a Reserva de Espaço de Log cai [-74]. Então, na verdade, está devolvendo algum espaço que foi reservado para a parte de encaminhamento da transação (LOP_INSERT_ROWS [178]). Como você pode ver, o sistema de reserva de espaço de log é muito conservador — o INSERT reserva mais espaço do que o DELETE devolve.
Reversões e backups diferenciais
Se um banco de dados tem um backup completo, uma transação atualiza 100.000 registros, mas a transação é revertida, por que um backup diferencial faz tantos dados? Certamente a reversão da transação significa que nada mudou? A peça do quebra-cabeça que falta aqui é que reverter uma transação não elimina todas as alterações feitas pela transação. Como vimos, o rollback deve gerar registros de log de compensação, pois o rollback deve gerar outras alterações para compensar a parte direta da transação. Os cabeçalhos de todas as páginas afetadas foram alterados pelo menos duas vezes. Um para atualizar o LSN da página para a parte de encaminhamento da transação e uma para atualizar o LSN da página para a parte de reversão da transação. Em ambos os casos, a atualização fará com que a extensão seja marcada como alterada no bitmap diferencial. Não importa qual foi a mudança, apenas que algo na extensão mudou. Não há como excluir essas extensões do backup diferencial.
Resumo
Neste artigo, examinamos os registros de log. Os registros de log são o núcleo dos mecanismos de log e recuperação. Cada alteração em um banco de dados tem um registro de log associado a ela. Cada registro de log descreve uma pequena alteração. Uma grande mudança tem vários registros de log dentro de uma única transação. Existem muitos tipos diferentes de registros de log e analisamos alguns deles.
O log de transações é um tópico essencialmente grande e alguns artigos não são suficientes para revelar todos os detalhes. Portanto, se você deseja obter informações mais detalhadas, sugiro que leia o seguinte livro:SQL Server Transaction Log Management de Tony Davis e Gail Shaw e este artigo:Gerenciamento de log de transações.
Leia também:
Mergulhe no log de transações do SQL Server — Parte 1
Mergulhe no log de transações do SQL Server — Parte 2