A regra
Escreva no log, e force o log para o disco, antes de escrever a página de dados. Em inglês, write-ahead logging.
- Se a página foi gravada e o log não, não há como saber o que desfazer
- Se o log foi gravado e a página não, dá para refazer
- A ordem é a única coisa que separa um banco confiável de um arquivo
O que acontece na partida
- Passagem 1, refazer. Lê o log do começo ao fim e reaplica tudo, inclusive o que já estava no disco
- Passagem 2, desfazer. Volta pelo log desfazendo as transações que não têm
COMMIT
- Ao fim, o banco contém exatamente as transações confirmadas
Refazer precisa ser idempotente: aplicar duas vezes tem que dar o mesmo resultado que aplicar uma.
Por que refazer o que já está no disco?
Não seria mais rápido refazer só o necessário?
- Seria, e é o que os bancos reais fazem
- Para isso é preciso saber qual versão do log cada página já reflete
- Isso é o número de sequência de log, a tabela de páginas sujas e o checkpoint
- Nós lemos o log inteiro. Mais lento, e muito mais fácil de entender
O critério de pronto, enfim
Um SELECT com WHERE, dentro de uma transação, e o banco volta consistente depois do kill -9 no meio do commit.
- Se o
kill vier antes do fsync do commit: a transação não aconteceu
- Se vier depois: a transação aconteceu, e o refazer a reconstrói
- Não existe meio termo. É isso que os testes de aceitação verificam