O funcionamento do Log especialmente no Microsoft SQL Server é um conceito amplamente explorado em qualquer entrevista de emprego e deve ser muito bem conhecido por todos que trabalham com bancos de dados porque mais importante que fazer uma pesquisa é saber como ela é realizada pelo servidor SQL e, com este conhecimento, o que pode ou deve ser melhorado para menor custo de execução.
Para entender o que é o log do servidor de banco de dados você precisa primeiramente conhecer os tópicos abaixo.
O servidor SQL possuí 2 arquivos fundamentais para seu funcionamento, o arquivo de dados (.mdf) e os arquivos de log (.log).
O arquivo .mdf é conhecido como arquivo primário e é criado na criação do banco de dados. Este tipo de arquivo é obrigatório e separado para cada banco de dados.
Conforme a necessidade podemos expandir o banco de dados e para isto são usados arquivos .ndf, arquivos de expansão do banco de dados. Isto é feito porque estes 'arquivos de expansão' podem ser colocados em discos diferentes (distribuindo a carga / uso dos discos / controladoras de disco). Este tipo de arquivo é opcional.
O terceiro tipo de arquivo é o arquivo tipo log que armazena as tarefas executadas pelo servidor SQL criando um 'inventário' do que foi feito e é fundamental, no MS SQL Server, para o funcionamento e manutenção da base de dados. Este tipo de arquivo é fundamental.
O quarto tipo de arquivo no servidor SQL é o arquivo de backup. O backup salva as informações do banco de dados num arquivo que permite recuperar o banco de dados no caso da perda do banco de dados por um acidente grave, como um 'crash' ( queima ) de um disco onde a base de dados se encontra.
Veremos a seguir que temos 3 tipos de backup : O Completo, o Diferencial e o do Log de transações. Como veremos a seguir o backup está amarrado ao modelo de recuperação do banco de dados que desejamos e depende da utilização / atualização do banco de dados.
Os nomes dos arquivos de bancos de dados seguem um padrão que pode ser mudado caso o administrador do banco deseje. Abaixo menciono o formato
padrão do nome do arquivo de backup :
backup -> extensão : .bak Nome do arquivo completo : BD_DD_MM_AAAA_HHMM.bak
O primeiro detalhe que você precisa saber sobre qualquer banco de dados SQL é que eles nunca processam 2 coisas ao mesmo tempo, ou seja, em paralelo, isto falando estritamente das atividades do banco de dados . O motivo é simples, um processo poderia 'interferir' num outro processo de outro usuário.
Só para citar um exemplo o usuário número 1 poderia fazer um update numa tabela e o usuário número 2 poderia ler os dados dessa tabela que está sendo atualizada, ou seja, leria as informações que na realidade estão apenas num 'rascunho' de algum processo. No final o usuário Número 1 cancela a atualização dele ( roollback ) e com isto o usuário número 2 teria lido informações que nunca realmente estiveram no banco de dados. Por isso o isolamento / enfileiramento de transações é fundamental, entre outros.
Por isso cada uma das atividades nos servidores sql são 'separadas e enfileiradas' ( em inglês, queued ) fazendo com que um processo seja feito em sua totalidade antes de começar outro processo.
Chamamos cada um desses 'processamentos ou tarefas' executadas no servidor de transações.
Exemplificando transação pode ser uma tarefa qualquer do servidor sql, um simples select, um update ou mesmo uma tarefa interna de manutenção dos índices de uma tabela.
Contudo podemos 'agrupar as tarefas' de maneira a executar um processo mais complexo. Com isso uma transação pode ser um grupo determinado de 'tarefas' agrupadas numa única 'transação' .
O servidor cria uma 'marca' chamada de 'checkpoint' marcando o inicio da transação ( vide begin transaction ) e executa as tarefas...no final ou ele executa um fim de processo OK ( commit transaction ) ou um volta-tudo ( rollback transaction ) desfazendo tudo que foi feito desde o 'checkpoint'.
Explicando melhor, no SQL server temos a necessidade de 'encadear' transações, ou seja, fazer um lote de transações para executar uma operação bancária, por exemplo, temos uma operação de débito em uma conta e crédito em outra conta e ambas as operações estão amarradas numa única tarefa composta por muitas transações. E pode ficar tranquilo que temos operações no banco de dados que envolvem literalmente centenas de transações e esse conceito de lote de transações está amarrada com a ideia fundamental do tudo ou nada, ou seja, ou processa tudo ou não processa nada.
Imagine um processo com centenas de passos e ocorreu um erro neles. Imagine o trabalho que daria para descobrir o ponto onde ocorreu o erro e a partir daí o que deveria ser retornado. Daria um trabalhão danado além de estar sujeito a erros da manipulação dos dados, teríamos que fazer um processo para tudo ok e outro para quando ocorre um erro.
Este conceito é fundamental para o conceito de integridade do banco de dados porque ele deve estar sempre num estado 'estável', ou seja, sabemos onde ele está e nada esta pendente, portanto podemos começar um novo processo ou executar novamente um processo que anteriormente deu erro.
No caso de uma transação ( processo ) ser muito longo o servidor sql pode 'congelar' a transação atual e ir atender outro
processo.
Contudo ele reserva os recursos que o primeiro processo está usando e se o segundo processo tentar acessar os
recursos reservados para o primeiro processo de maneira a alterar eles a segunda transação será barrado
( terá um lock ) e terá que aguardar até o anterior terminar.
Note que os processos do servidor sql são coisas de segundos e raramente um usuário notará esse 'atraso' na sua pesquisa pelo lock (travamento) de sua transação.
O LOG é um arquivo texto comum onde o SQL Server escreve tudo que está fazendo antes de fazê-lo. Chamamos isso de write ahead ( escrita na frente, adiantada ). Cada update, select, literalmente tudo porque tudo consome recursos do servidor SQL é gravado neste arquivo para efeito de controle de processos.
Dentro do log temos os pontos de controle ( checkpoints ) que podem controlar, por exemplo, um lote de transações. Por exemplo, uma transação retira o valor de uma conta bancária. Outra transação deposita este valor em outra conta. Se a segunda transação falhar é melhor que a primeira nunca tenha sido feita senão teremos 2 problemas para resolver (1-retornar o valor da primeira conta e 2-repetir a transferência) e não um só ( 1-repetir a transferência ).
Um checkpoint faz isso, ele determina o começo de um conjunto de transações ( como no comando
Begin Transaction). Ele define um agrupamento de transações permitindo o 'tudo ou nada'.
Aí o servidor executa um monte de operações ( outras transações ). Se tudo estiver ok podemos executar o comando
'commit transaction' que finaliza o lote de transações com sucesso. Contudo, se algo der errado, em
qualquer ponto do processo, o servidor pode desfazer tudo que foi feito até o 'checkpoint' da transação, chamamos
isso de 'roolback transaction'.
Uma transação são 'tarefas encadeadas ou dependentes' uma da outra onde ou todas elas precisam ser executadas com sucesso ou nenhuma delas deverá ser executada . É o caso de uma operação bancária onde o dinheiro de uma conta vai para outra conta...imagine a zona se o dinheiro sair de uma conta e não for parar na outra...vão ser 2 pessoas diferentes reclamando por causa desse problema, uma porque pagou a conta e recebeu uma nova cobrança da mesma compra e outra porque deveria ter recebido o valor no dia x e recebeu bem depois...ele pode até cobrar juros por isso.
Dependendo do fabricante e de como o banco de dados é estruturado o uso do log muda.
No Microsoft SQL Server ele é totalmente dependente do LOG, ou seja, se o LOG parar o banco de dados para também. Não é possível desligar o LOG no Microsoft SQL Server.
Já no banco de dados Oracle ele possuí uma estrutura de controle de transações independentes do log e podemos desligar o log sem perder o controle das transações do servidor SQL Server da Oracle. No Oracle se o log parar ou se for desligado o banco de dados continua funcionando normalmente.
Tenha em mente que todo backup representa um custo para o servidor SQL. Como disse inúmeras vezes, no SQL não temos nada de graça, é como uma teia de aranha que ao puxar de um lado estica do outro.
O LOG está ligado diretamente a confiabilidade dos dados do Servidor, especialmente na recuperação do banco de dados no caso de um acidente. Sendo assim, genericamente,temos 3 tipos de LOG: Um que não se importa com a perda de dados, um que tolera a perda de dados e outro que não tolera a perda de dados .
1 - LOG de baixa confiabilidade : Neste caso a perda de informações não é critica no processo. Você deve pensar que ninguém usa esse método mas na realidade é o mais usado porque dá menos trabalho, mas existe critérios para seu uso :
1.1 - Existe pouca atualização das informações. Um backup do mês passado terá a mesma informação que esta atualmente na tabela. Por exemplo uma tabela com os estados brasileiros ( Unidades Federativas - UF ). Ela praticamente nunca sofre qualquer alteração e muitas tabelas nos sistemas trabalham com dados estáticos que tirado um backup ele servirá por muito tempo.
1.2 - Os dados da tabela não são tão importantes que justifiquem algo mais. Por exemplo, uma tabela de preços do mês passado é muito próxima dos preços atuais ( no caso de uma inflação controlada). No caso de falha podemos retornar um backup antigo e atualizar, na mão, alguns desses dados. Podemos ter uma cópia das infos atuais num Excel ou coisa parecida para nos guiar numa recuperação das informações da tabela.
O backup comum para este processo é o Backup FULL ou Backup Completo. Ele salva tudo da tabela num arquivo único, ou seja, para recuperar a tabela só um único backup é o suficiente.
2 - LOG de média confiabilidade : Neste caso é admitida a perda de informações por um tempo máximo, digamos, nos últimos 5 minutos. Neste caso existe um processo de backup automático que se repete em determinado período e se houver a perda de dados o último backup foi tirado a poucos minutos e muito pouco ou nada será perdido.
Lembre-se que o backup é um custo para o servidor e isto carrega o sql server com mais uma tarefa. Contudo esse 'backup' costuma ser 'diferencial', ou seja, apenas o que foi alterado desde o último backup é salvo no novo backup.
Com isto, o backup diferencial, temos a perda de dados desde o último backup, digamos, 5 minutos atras. O chato deste tipo de backup é que gera muitos arquivos de backup ( um a cada 5 minutos no exemplo ) e para restaurar o banco de dados precisamos do último 'backup full' do banco de dados e restaurar, um por um, dos backups diferenciais salvos anteriormente.
Chamamos de backup de média confiabilidade porque ele admite a perda de dados entre os backups efetuados porque o backup do arquivo de LOG ( que contém as últimas alterações do banco de dados ) não é feito. Com isto perdemos as modificações desde o último backup feito.
Para finalizar menciono o grande problema desse backup...se um dos arquivos de backup for corrompido todo o banco de dados não poderá mais ser restaurado na condição planejada ( até o último backup ). O banco de dados só será 'retornado' até a ocorrência do erro. Além disso se você for salvar esse 'backup' terá que salvar um monte de arquivos.
3 - LOG de alta confiabilidade : Neste caso não é admitida nenhuma perda de dados e pode ser o mais custoso para o SQL Server porque é feito durante a operação normal do banco de dados.
O Backup neste caso é feito tirando um 'snapshot' ( digamos em português, uma cópia quente ) do banco de dados, ou seja, é feito um congelamento do banco de dados, tirado uma cópia e o que foi alterado desde o último backup é salvo e, em seguida, o banco de dados é liberado e o 'backup' poderá ser utilizado para recuperar o banco de dados naquele exato momento.
O backup do tipo 'alta confiabilidade' é chamado de diferencial, ou seja, tudo que foi alterado desde o último backup é salvo no arquivo de backup bem como o arquivo de log contendo as últimas modificações no banco de dados.
Sendo assim neste modelo temos o banco de dados exatamente no último momento que foi salvo. Para restaurar o banco de dados
temos que processar / restaurar:
1-O último backup completo / full.
2-Todos os backups incrementais.
3-O arquivo de Log até o momento que desejamos recuperar o banco de dados.
Com isto podemos notar que este modelo é o mais seguro porque perde menos informação mas também é o mais trabalhoso tanto para
o SQL como para a recuperação do banco de dados.
O modo de recuperação está diretamente ligado ao LOG, ou seja, o LOG é definido conforme o modo de recuperação do servidor.
No caso 1 - LOG de baixa confiabilidade chamamos de 'modo de recuperação simples'. No caso de falha faremos a recuperação dos dados do servidor através do último backup do banco de dados. Note que neste backup não salvamos o log mas sim somente o banco de dados e o banco de dados será retornado exatamente como estava no momento do backup.
No caso 2 - LOG de média confiabilidade chamamos de 'modo de recuperação Bulk-Logged'. No caso de falha faremos a recuperação dos dados do servidor através do último backup do banco de dados e dos arquivos de log. Contudo o 'backup do log' não é completo e as informações não importantes, que o servidor pode reconstruir sozinho, não são salvas. Com isto após o banco retornar será necessário que o SQL faça um certo 'reprocessamento' para tudo voltar ao normal.
No caso 3 - LOG de alta confiabilidade chamamos de 'modo de recuperação Full ou Completo'. No caso de falha faremos a recuperação dos dados do servidor através do último backup do banco de dados e dos arquivos de log salvos. Neste caso a recuperação do banco de dados é exatamente como ele era no momento de que o último log foi gerado.
Para entender o log você deve conhecer os princípios ACID que regem o funcionamento de todo servidor SQL.
ACID são funcionalidades implementadas nos bancos de dados que garantem desde a qualidade da informação até seu
funcionamento e manutenção.
ACID são as principais propriedades que um banco de dados deve ter para que
haja garantia que os dados são confiáveis no banco de dados
.
ACID é uma abreviação de Atomicidade, Consistência, Isolamento e Durabilidade .
1. Atomicidade : Isso significa que uma transação é uma operação tudo ou nada. Se qualquer parte da transação falhar, a transação inteira será revertida e o banco de dados permanecerá inalterado. No SQL Server, isso é imposto por mecanismos como transações e de controle como os comando rollback e commit.
2. Consistência : Uma transação deve levar o banco de dados de um estado válido para outro,ou seja, ele parte de um ponto estável e vai para outro ponto estável onde nada fica pendente. Após a transação ser executada, o banco de dados ainda deve atender a todas as regras definidas (restrições ( constraints ), gatilhos ( triggers ), etc.). No SQL Server, as restrições (por exemplo, chaves estrangeiras, restrições exclusivas) garantem a consistência estabelecendo regras que não podem ser quebradas.
3. Isolamento: As transações são executadas isoladamente umas das outras, o que significa que o estado intermediário de uma transação ( ou seja, ela ainda não foi terminada completamente ) não deve ser visível para outras transações. O SQL Server fornece vários níveis de isolamento como Leitura não confirmada (read uncommited), Leitura confirmada (read commited), Leitura repetível e Serializable ( enfileiramento ) para controlar a visibilidade dos dados durante as transações.
4. Durabilidade : Uma vez que uma transação foi confirmada, ela é permanente, mesmo em caso de falha do sistema. O SQL Server garante a durabilidade usando logs de transações que rastreiam todas as alterações, para que possam ser reaplicadas em caso de falha.
Juntas, essas propriedades garantem que o Microsoft SQL Server possa manipular transações de forma confiável e robusta, preservando a integridade e a estabilidade do banco de dados mesmo sob uso simultâneo e falhas inesperadas.
Profissionalmente você terá situações que o banco de dados apresenta problemas de integridade que precisam ser corrigidas contudo todo mundo que está utilizando os bancos de dados com problemas não percebem o problema porque o SQL server 'mascara' o problema.
É o caso da integridade do banco de dados com problemas onde o encadeamento das páginas de dados foi perdida. Dando um select count na tabela temos um número de registros e um select count desc temos outro número de registros porque quando o sql encontra o problema ele não 'crasha', mas sim para a pesquisa e retorna o que conseguiu obter. Para todos usuários os resultados estão corretos mas o DBA sabe que o banco de dados está com problema e não está retornando a resposta correta para a pesquisa. Dica : Vide alertas do SQL Server.