Ativar/desativar o modo Wal2
- O modo "Wal2" do SQLite é muito semelhante ao modo "wal (Write-Ahead Logging)".
- Para mudar o banco de dados para o modo wal2, use o comando
PRAGMA journal_mode = wal2;.
- Não é possível mudar diretamente do modo "wal" para o modo "wal2"; primeiro é preciso mudar para o modo rollback.
- Para mudar um banco de dados no modo wal para o modo wal2, use
PRAGMA journal_mode = delete; e depois o comando PRAGMA journal_mode = wal2;.
- Um banco de dados no modo wal2 só pode ser acessado por uma versão do SQLite compilada a partir desse branch.
- Ao tentar usar outra versão do SQLite, ocorre o erro SQLITE_NOTADB.
- Para mudar um banco de dados no modo wal2 para o modo rollback e permitir acesso por todas as versões do SQLite, use o comando
PRAGMA journal_mode = delete;.
Vantagens do modo Wal2
- No modo wal tradicional, quando o gravador escreve dados no banco de dados, ele não modifica diretamente o arquivo do banco, e sim acrescenta novos dados ao arquivo "-wal".
- As operações de leitura leem dados tanto do arquivo original do banco de dados quanto do arquivo "-wal".
- Em algum momento, os dados do arquivo "-wal" são copiados para o arquivo do banco de dados; isso é chamado de "checkpoint".
- O checkpoint pode ser executado explicitamente por meio de
PRAGMA wal_checkpoint ou sqlite3_wal_checkpoint_v2(), ou automaticamente ao configurar PRAGMA wal_autocheckpoint (configuração padrão).
- O checkpointer não bloqueia o gravador, e o gravador também não bloqueia o checkpointer.
- Porém, se o gravador escrever no banco durante um checkpoint, novos dados serão acrescentados ao fim do arquivo wal, e o arquivo wal pode continuar crescendo.
- No modo wal2, não existe o problema de o arquivo wal crescer indefinidamente, mesmo que o checkpointer não tenha chance de concluir sem ser interrompido.
- No modo wal2, são usados dois arquivos wal ("-wal" e "-wal2") em vez de um.
- Quando os dados são gravados, o gravador começa acrescentando novos dados ao primeiro arquivo wal.
- Quando o primeiro arquivo wal cresce o suficiente, o gravador passa a acrescentar dados ao segundo arquivo wal.
- Depois disso, o primeiro arquivo wal pode passar por checkpoint e, quando o segundo arquivo wal também crescer o suficiente e o primeiro arquivo tiver passado por checkpoint, volta-se ao primeiro arquivo.
Programação de aplicações
- Do ponto de vista do usuário, a principal diferença entre os modos wal e wal2 está relacionada ao checkpoint.
- No modo wal, é possível tentar um checkpoint a qualquer momento, mas no modo wal2 o checkpoint só é possível depois que o gravador alterna para o "outro" arquivo wal.
- No modo wal, após o commit de uma transação, o wal-hook (callback) é chamado usando como argumento o número total de páginas do arquivo wal.
- No modo wal2, o wal-hook é chamado usando como argumento o total de páginas ainda não submetidas a checkpoint nos dois arquivos wal, ou 0 caso o "outro" arquivo wal esteja vazio ou já tenha passado por checkpoint.
- Recomenda-se que clientes usem no banco de dados em modo wal2 a mesma estratégia de checkpoint usada no modo wal.
- O wal-hook é chamado depois que a transação é confirmada em disco e o bloqueio do banco de dados é liberado, mas isso ocorre dentro da chamada
sqlite3_step().
- Em sistemas BEGIN CONCURRENT, em vez de executar o checkpoint dentro do wal-hook, pode-se usar uma thread que adie esse trabalho até que o mutex da aplicação seja liberado.
Opinião do GN⁺
- O modo wal2 do SQLite oferece uma nova forma de journaling que melhora a concorrência e a eficiência do banco de dados.
- Resolver o problema de crescimento infinito do arquivo wal é importante para melhorar a estabilidade e o desempenho do sistema.
- Com a adoção do modo wal2, os desenvolvedores precisam rever a estratégia de checkpoint do banco de dados e implementar uma lógica de checkpoint adequada para obter melhor concorrência.
1 comentários
Comentários no Hacker News
Bedrock
Link para o left-right primitive, uma técnica semelhante ao modo WAL2.
O Microsoft SQL Server usa uma arquitetura semelhante, mas aloca Virtual Log Files (VLF) dentro do arquivo de log físico (no disco), em vez de usar arquivos de log separados. Os VLF são alocados em um ring buffer e podem chegar a milhares.
Dá para perceber que esse recurso ainda não foi lançado.
Sempre me preocupei com o fato de que o WAL existe para ajudar a manter a integridade dos dados e permitir a recuperação após falhas. Mas o próprio arquivo é gravado em lotes (confirmado de forma confiável no disco), e não após cada alteração no banco de dados, para ganhar desempenho. Isso não compromete o objetivo? De forma mais geral, sem se limitar a bancos de dados, nunca encontrei uma resposta para isso.
Fico curioso sobre como isso vai afetar novos sistemas distribuídos de SQLite, como o Litestream.
Então isso é basicamente double buffering para banco de dados? Faz sentido.
O modo WAL2 foi incluído nos benchmarks da pesquisa sobre o backend HC-tree.