Skip to content

knowledgeC.db-wal : retrouver les événements récents

Pourquoi les derniers événements knowledgeC ne sont souvent que dans le WAL, comment marchent trames, sels et checkpoints, et comment lire ses changements.

Publié le 10 min de lecture

En bref. knowledgeC.db fonctionne en mode WAL de SQLite : les nouvelles transactions sont ajoutées à la fin de knowledgeC.db-wal et ne sont recopiées dans le fichier principal qu'au moment d'un checkpoint. D'ici là, les événements les plus récents n'existent que dans le WAL, et les lignes supprimées par une transaction récente sont encore dans le fichier principal. Collectez le -wal avec la base, travaillez sur des copies car ouvrir l'original peut déclencher un checkpoint, et lisez le WAL comme une liste de versions de pages validées, contrôlées par des sels et des sommes de contrôle. KnowledgeC Parser applique les trames validées et marque chaque ligne « only in the WAL » (présente uniquement dans le WAL) ou « removed by the WAL » (supprimée par le WAL).

Pourquoi le WAL compte pour knowledgeC

De nombreux articles sur la base knowledgeC interrogent knowledgeC.db seul. Sur un Mac allumé ou éteint depuis peu, on passe souvent ainsi à côté de la partie de la chronologie qui compte le plus : les dernières heures avant la collecte. CoreDuet écrit les lignes quand les intervalles se terminent, ces lignes vont dans le WAL et n'atteignent le fichier principal qu'au checkpoint de SQLite. Un analyste qui n'examine que le fichier principal voit une chronologie qui s'arrête trop tôt, et peut conclure que le Mac était inactif alors qu'il ne l'était pas.

L'inverse arrive aussi. La purge liée à la conservation supprime les anciennes lignes ; cette suppression est une transaction du WAL, et le fichier principal conserve les anciennes lignes jusqu'au checkpoint suivant. Les deux cas ne sont visibles que si vous disposez des deux fichiers et les comparez.

Comment fonctionne le WAL de SQLite

La référence est la documentation SQLite sur la journalisation en écriture anticipée (write-ahead logging) et sur le format du fichier WAL. En résumé : la base est un ensemble de pages de taille fixe. En mode WAL, un processus d'écriture ne modifie jamais directement les pages du fichier principal. Il ajoute de nouvelles versions des pages modifiées à la fin du fichier -wal ; les lecteurs cherchent d'abord la dernière version validée d'une page dans le WAL, puis se rabattent sur le fichier principal.

L'en-tête du WAL

Le -wal commence par un en-tête de 32 octets, en big-endian :

DécalageTailleChamp
04Magic : 0x377f0682 ou 0x377f0683 (détermine l'ordre des octets de la somme de contrôle)
44Version du format de fichier (3007000)
84Taille de page de la base
124Numéro de séquence du checkpoint
164Salt-1
204Salt-2
248Somme de contrôle des 24 premiers octets

Les trames

Après l'en-tête viennent les trames : un en-tête de trame de 24 octets suivi d'une page complète.

DécalageTailleChamp
04Numéro de page
44Taille au commit : pour la dernière trame d'une transaction, la taille de la base en pages après le commit ; 0 sinon
84Salt-1, copié depuis l'en-tête du WAL
124Salt-2, copié depuis l'en-tête du WAL
168Somme de contrôle cumulative sur l'en-tête et toutes les trames jusqu'à celle-ci

Quelles trames comptent

Une trame n'est valide que si ses sels correspondent à ceux de l'en-tête du WAL et si sa somme de contrôle correspond à la somme cumulée calculée depuis le début du fichier. La lecture s'arrête à la première trame qui échoue à l'un de ces tests. Parmi les trames valides, seules celles qui vont jusqu'à la dernière trame de commit (taille au commit non nulle) incluse appartiennent à des transactions validées. Les trames suivantes forment une transaction inachevée et sont ignorées par SQLite : elles ne doivent donc pas être traitées comme du contenu de la base. Si une page apparaît dans plusieurs trames validées, c'est la plus récente qui l'emporte.

Checkpoints et réinitialisations

Un checkpoint recopie la dernière version validée de chaque page du WAL vers le fichier principal. Par défaut, SQLite en lance un automatiquement lorsque le WAL atteint environ 1000 pages, et normalement lorsque la dernière connexion à la base se ferme. Après un checkpoint, le processus d'écriture suivant peut faire repartir le WAL du début : salt-1 est incrémenté et salt-2 change, et le fichier n'est pas nécessairement tronqué. Des trames de la génération précédente peuvent donc subsister après les trames valides. Leurs sels ne correspondent plus, SQLite les ignore donc ; ce sont des versions de pages périmées, qui ne font pas partie de la base actuelle.

Le fichier -shm

knowledgeC.db-shm est l'index du WAL : une mémoire partagée qui aide les connexions à trouver rapidement les pages dans le WAL. Il ne contient aucune donnée absente du WAL et peut être reconstruit à partir de celui-ci. Collectez-le avec les deux autres fichiers par souci d'exhaustivité, mais le contenu validé provient du -wal.

Deux cas qui changent une chronologie

Les lignes présentes uniquement dans le WAL

Une ligne insérée depuis le dernier checkpoint n'existe que sous forme de version de page dans le -wal. Analysez le fichier principal seul, et la ligne est absente. Ce sont en général les lignes les plus récentes : le trou se situe donc à la fin de la chronologie, juste avant la collecte.

Les lignes supprimées par le WAL

Un DELETE validé produit, dans le WAL, de nouvelles versions de pages sans la ligne. Le fichier principal contient toujours l'ancienne page, avec la ligne. Lire la base « comme SQLite le ferait » masque la ligne ; lire le fichier principal seul la montre. La comparaison des deux vues vous apprend que la ligne existait et qu'elle a été supprimée après le dernier checkpoint.

Dans knowledgeC, la cause habituelle est la purge des anciens événements liée à la conservation. Une ligne supprimée par le WAL ne prouve pas à elle seule une suppression délibérée ; comparez sa date à la fenêtre de conservation que vous avez mesurée sur les éléments de preuve avant d'en tirer quoi que ce soit. Les lignes modifiées sur place gardent leur identité et affichent simplement leurs nouvelles valeurs.

Travailler en sécurité

  • N'ouvrez jamais l'original. Ouvrir une base en mode WAL avec un client SQLite ordinaire peut déclencher un checkpoint : les pages du WAL sont écrites dans le fichier principal, et le WAL peut être réinitialisé. Les deux cas ci-dessus disparaissent alors.
  • Conservez une copie intacte. Calculez l'empreinte des trois fichiers tels que collectés, et analysez une deuxième copie.
  • Sachez quelle vue vous regardez. Un client SQLite qui dispose des deux fichiers affiche la base avec le WAL appliqué, et peut déclencher un checkpoint sur votre copie. Une copie du fichier principal sans son -wal montre l'état au dernier checkpoint. Il vous faut les deux vues pour voir ce que le WAL a ajouté et supprimé.
  • Consignez ce qui vous manquait. Si le -wal n'a pas été collecté, dites-le dans le rapport : l'absence d'événements récents est alors une lacune de la collecte, pas une constatation. La façon de le collecter est décrite dans knowledgeC.db : emplacement et collecte des flux Biome.

Comment KnowledgeC Parser traite le WAL

KnowledgeC Parser lit les fichiers en lecture seule dans votre navigateur et associe chaque knowledgeC.db au -wal du même nom. Ensuite, il :

  1. vérifie l'en-tête du WAL : magic, taille de page égale à celle de la base, somme de contrôle de l'en-tête ;
  2. lit les trames dans l'ordre tant que les sels correspondent et que la somme de contrôle cumulée est correcte, et s'arrête au premier échec avec une note comme « checksum mismatch at frame N » ou « salt mismatch » ;
  3. n'applique que les transactions validées, indique combien de trames d'une transaction inachevée ont été ignorées, et superpose la dernière version validée de chaque page au fichier principal ;
  4. lit ZOBJECT deux fois, avec et sans le WAL, et fait correspondre les lignes par numéro d'enregistrement et UUID.

Chaque événement knowledgeC porte alors, le cas échéant, l'un de ces deux marqueurs : only in the WAL (présent avec le WAL, absent du fichier principal) ou removed by the WAL (présent dans le fichier principal, supprimé par une transaction validée du WAL). Le rapport de fichier résume le résultat sous la forme « WAL applied: N committed frame(s), X row(s) only in the WAL, Y row(s) removed by it » (WAL appliqué : N trames validées, X lignes présentes uniquement dans le WAL, Y lignes supprimées par lui). Lorsqu'une base en mode WAL arrive sans son -wal, le rapport le signale et avertit que des événements récents peuvent manquer. Les trames périmées des anciennes générations du WAL ne sont pas utilisées.

Un exemple synthétique : FIN-MBP-03

La collecte d'exemple fournie avec l'outil est synthétique ; le Mac, l'utilisatrice et les événements sont fictifs. Sur le MacBook FIN-MBP-03, le fichier principal du knowledgeC.db système contient des lignes écrites jusqu'à environ 10:00 UTC le 2026-09-14. Tout ce qui a été écrit ensuite se trouve dans une transaction validée supplémentaire du WAL.

Analysée sans le -wal, la base montre le dernier intervalle de déverrouillage de la matinée de dana.whitlock se terminant à 09:58 UTC, lorsqu'elle a verrouillé le Mac pour aller déjeuner, et rien après. Avec lui, le rapport affiche « WAL applied » avec quelques dizaines de lignes présentes uniquement dans le WAL et une ligne supprimée par lui. Parmi les lignes présentes uniquement dans le WAL :

  • un intervalle de déverrouillage /device/isLocked commençant à 10:04:31 UTC (ZSECONDSFROMGMT 7200, soit 12:04 heure locale) et se terminant à 10:49 UTC ;
  • des intervalles /app/usage pour Safari, Finder, Utilitaire d'archive, Terminal et Réglages Système dans cette fenêtre.

La ligne supprimée par le WAL est un intervalle /app/usage pour com.apple.mail le 2026-08-10 : un ancien événement purgé au titre de la conservation, toujours présent dans le fichier principal. C'est une bonne illustration de la raison pour laquelle « supprimé » ne doit pas être lu comme « effacé ».

Ce que le WAL apporte ici, c'est l'existence et la chronologie d'une activité pendant la pause déjeuner. Il ne dit pas qui était au clavier et ne nomme ni fichiers ni commandes. Pour cette interprétation, et pour la corroboration par Biome et d'autres sources, voir qui était au clavier. Pour reproduire l'exemple, chargez la collecte d'exemple depuis la page d'accueil ou suivez analyser knowledgeC et Biome dans votre navigateur.

Ce que le WAL ne vous dit pas

  • Quand une trame a été écrite. Les trames ne portent aucun horodatage. Une ligne du WAL a été validée après le dernier checkpoint ; l'heure de son événement provient de ZSTARTDATE et ZENDDATE, en temps absolu Mac, pas de sa position dans le fichier.
  • Quoi que ce soit d'antérieur à la dernière réinitialisation. Les trames périmées d'une génération précédente sont ignorées par SQLite et par l'outil ; elles sont hors de la base actuelle.
  • Ce qui a été supprimé avant le dernier checkpoint. Une fois une suppression intégrée par un checkpoint, la ligne a disparu des deux vues ; les résidus dans l'espace libre relèvent du carving, hors du périmètre de cette méthode.

Articles liés

Articles liés

Ce que knowledgeC.db enregistre sous macOS, où il se trouve, comment lire ZOBJECT et ses flux, convertir ses horodatages et ce que ces données ne prouvent pas.
knowledgeC.db ou Biome ? Les différences entre ces deux sources d'activité macOS, la correspondance de leurs flux et ce qu'on trouve sur les versions récentes.
Pas à pas : charger knowledgeC.db, son -wal et les flux SEGB de Biome dans un parseur gratuit, filtrer une période, étudier les sessions et exporter.