Como arquivos de banco de dados SQLite podem ser corrompidos
Aprofundamento CEVIU
Aprofundamento
O SQLite é uma biblioteca de banco de dados embutida, não um serviço cliente-servidor. Ele opera diretamente sobre arquivos no sistema de arquivos, o que dá leveza, mas transfere para o desenvolvedor a responsabilidade por sincronização, locking e integridade física do arquivo. A corrupção não surge de falhas lógicas no SQL ou erros de schema, mas de interferências no nível de I/O: escritas concorrentes sem coordenação, fechamento acidental de file descriptors compartilhados, backups feitos enquanto WAL está ativo, ou mesmo renomeação de arquivos abertos. Esses cenários são silenciosos: o SQLite não bloqueia a operação, mas o dano aparece depois, em leituras truncadas, páginas corrompidas ou falhas de recuperação automática.
Importante: SQLite não é 'imune' à corrupção porque usa transações ACID, ele é resistente *quando usado conforme projetado*. Mas o projeto pressupõe que ninguém vai ler o arquivo .db diretamente com open()/read(), que ninguém vai chamar close() em um fd já usado por outra thread, e que o sistema de arquivos fará locking como prometido. Quando essas suposições quebram, como em NFS com bugs de POSIX lock ou aplicações que linkam duas cópias da biblioteca, a proteção desaparece.
O que mudou
A versão 3.51.0 (2025-11-04) introduziu defesas específicas contra corrupção causada por close() acidental em ambientes multi-processo com WAL ativado, um problema já documentado desde 2013, mas agora mitigado parcialmente. Já a versão 3.47.0 (2024-10-21) trouxe o sqlite3_rsync, primeira ferramenta oficial para backup consistente de bancos ativos via SSH, antes disso, só havia soluções manuais (VACUUM INTO, backup API) ou riscos reais de cópia inconsistente. Isso fecha uma lacuna prática que afetava diretamente casos como o do KeePass, onde o uso de SQLite poderia ter evitado fragilidades de schema e incompatibilidades entre implementações como descrito na documentação oficial.
Por que isso importa
Para engenheiros de dados e devs que usam SQLite como camada de persistência local, em aplicativos desktop, CLI tools, ou pipelines de backfill, entender os vetores de corrupção é mais crítico que saber escrever bons índices. Um backfill mal orquestrado pode travar o arquivo durante escrita; um processo de backup que ignora o estado do WAL pode gerar cópias inutilizáveis; e uma integração com LLM que expõe o schema do SQLite via prompt injection [[LINK:/newsletter/ceviu-ti/manipulacao-insegura-de-saida-sql-injection-atraves-de-llm|como já alertado]] amplifica o risco de manipulação direta do arquivo. Corrupção aqui não é erro de aplicação: é falha de infraestrutura de dados, e, diferentemente de bancos distribuídos, não há replay automático nem detecção em tempo real.
Linha do tempo
SQLite 3.7.17 passa a emitir warnings ao detectar unlink de arquivo aberto ou múltiplos hard links
SQLite 3.8.1 começa a recusar file descriptors de baixa numeração para evitar sobrescrita acidental
SQLite 3.10.0 passa a resolver symbolic links para abrir o arquivo pelo nome canônico
SQLite 3.47.0 lança sqlite3_rsync para backups seguros de bancos ativos via SSH
SQLite 3.51.0 adiciona defesas contra corrupção por close() acidental em modo WAL multi-processo
Publicação da análise detalhada dos vetores de corrupção em SQLite
Perguntas frequentes
Posso fazer backup de um banco SQLite copiando o arquivo .db com 'cp' enquanto ele está em uso?
Não, se houver transações ativas ou WAL habilitado. Cópias com 'cp' ou 'rsync' sem coordenação capturam um estado inconsistente, parte antiga, parte nova. Use VACUUM INTO, a API de backup ou sqlite3_rsync (a partir da versão 3.47.0).
Qual é o risco real de usar SQLite em sistemas de arquivos de rede, como NFS?
Alto. SQLite depende de locking POSIX confiável, mas muitos NFS têm bugs nessa camada. Dois processos podem achar que têm exclusividade de escrita ao mesmo tempo, resultando em sobrescrita de páginas e corrupção irreversível. Evite NFS para bancos SQLite em produção.
Por que chamar 'close()' em um file descriptor usado por SQLite pode corromper o banco?
Em sistemas Unix, 'close()' remove todos os locks advisory do processo sobre aquele arquivo, mesmo os mantidos por outras threads via SQLite. As demais threads continuam operando sob falsa suposição de exclusividade, gerando escritas concorrentes e corrupção.
O SQLite detecta automaticamente se o arquivo foi renomeado ou tem hard links?
Sim, desde a versão 3.7.17 (2013). Ele emite mensagens SQLITE_WARNING no log ao detectar unlink de arquivo aberto ou múltiplos hard links. Mas isso não impede a corrupção, só sinaliza que o comportamento está indefinido.
Fontes
- sqlite.orgfonte original
- Categoria
- CEVIU Dados
- Publicado
- 03 de julho de 2026
- Editoria
- CEVIU Dados
