Em um sistema embarcado que desenvolvemos, apareceu a necessidade de armazenar contadores de forma segura. Como esses contadores correspondiam a valores monetários (semelhante a totalizadores de uma caixa registradora), o mecanismo de armazenamento deveria atender algumas exigências:
Em suma, o armazenamento desses totalizadores deveria ser uma transação ACID (atômica, consistente, isolada e durável). Como não era possível colocar um banco de dados no sistema embarcado, a única ferramenta que sobrava era o sistema de arquivos "cru". Optamos pelo ext3, que possui journaling. O journaling garante que a gravação de meta-dados é ACID.
A técnica descrita a seguir está em uso em milhares de equipamentos, com excelentes resultados e sem perdas de dados, exceto naturalmente quando acontece falha na CompactFlash.
Passos de gravação a cada atualização de contadores:
Passos de leitura ao ligar a máquina:
A transação assim gravada é atômica pois o arquivo só é válido se tiver sido completamente gravado. Em caso de qualquer interrupção, o arquivo fica com o somatório inválido, e é descartado na recarga.
O sistema de arquivos com journaling também é peça importante aqui pois garante que os meta-dados do arquivo nunca serão alterados pela metade. O arquivo nunca ficará num estado ilegível ou impossível de sobrescrever (ele pode sim ficar corrompido, mas isso o checksum detecta). Seria possível usar um sistema de arquivos não-journaling, mas a chance de falha causada por desligamento seria maior.
Também é consistente porque o somatório assim o garante. Se o somatório for calculado com algum recurso de criptografia, também será capaz de evitar tentativas de fraude (e.g. alguém plantar um arquivo).
A transação é naturalmente isolada pois apenas um processo é encarregado de gravar tais arquivos. Não foi necessária nenhuma medida no software para garantir a isolação.
E é durável pelo fato de ser gravada em modo síncrono. A chamada de gravação só retorna quando o arquivo estiver no disco. O programa pode ter absoluta certeza que o dado está salvo. Já uma gravação assíncrona pode ser indefinidamente adiada pelo sistema. e pode ocorrer fora de ordem. A maioria dos bancos de dados utiliza gravações síncronas como forma de garantir a durabilidade de transação.
O uso de dois arquivos também é componente crucial da durabilidade. Se houvesse apenas um arquivo, os contadores velhos estariam perdidos enquanto os novos estivessem sendo gravados. Uma falha nesse momento crucial, e tudo esaria perdido. (Problema semelhante ocorre numa cópia de segurança que é feita sempre sobre a mesma fita. Ainda o mesmo raciocínio é aplicável para armazenamento de dados em memória não-volátil, por mais rápida que seja.) Utilizamos dois arquivos, mas poderiam ser vários. Como a CompactFlash é lenta, optamos pelo mínimo suficiente.
Ao invés de gravar dois arquivos, como fizemos, poderíamos também utilizar um único arquivo, no estilo "redo log". Um redo log nunca é alterado, apenas estendido com os dados novos. Ele é ACID e tem a vantagem de permitir "rollback" para qualquer instante passado.
Como o projeto não exigia histórico dos contadores, não chegamos a cogitar o uso de redo log. O redo log pode ocupar bastante espaço em disco se os dados são atualizados freqüentemente. Uma máquina com CompactFlash pequena, que pode funcionar por anos a fio sem atualização do software, não teria como comportar um redo log "infinito".