knowledgeC.db-wal: aktuelle Ereignisse aus dem WAL retten
Warum neue knowledgeC-Ereignisse oft nur in knowledgeC.db-wal stehen, wie Frames, Salts und Checkpoints arbeiten und wie Sie neue und entfernte Zeilen lesen.
Kurz gesagt. knowledgeC.db läuft im SQLite-WAL-Modus: Neue Transaktionen werden an knowledgeC.db-wal angehängt und erst bei einem Checkpoint in die Hauptdatei kopiert. Bis dahin existieren die neuesten Ereignisse nur im WAL, und Zeilen, die eine kürzliche Transaktion gelöscht hat, stehen noch in der Hauptdatei. Sichern Sie die -wal zusammen mit der Datenbank, arbeiten Sie mit Kopien, weil das Öffnen des Originals einen Checkpoint auslösen kann, und lesen Sie das WAL als Liste festgeschriebener Seitenversionen, die durch Salts und Prüfsummen validiert werden. KnowledgeC Parser wendet die festgeschriebenen Frames an und markiert jede Zeile als „only in the WAL“ (nur im WAL) oder „removed by the WAL“ (durch das WAL entfernt).
Warum das WAL bei knowledgeC zählt
Viele Beiträge zur knowledgeC-Datenbank fragen nur knowledgeC.db ab. Auf einem laufenden oder gerade heruntergefahrenen Mac fehlt dabei oft genau der Teil der Zeitleiste, der Sie am meisten interessiert: die letzten Stunden vor der Sicherung. CoreDuet schreibt Zeilen, wenn Intervalle enden; die Zeilen landen im WAL und erreichen die Hauptdatei erst, wenn SQLite einen Checkpoint ausführt. Wer nur die Hauptdatei auswertet, sieht eine Zeitleiste, die zu früh endet, und schließt womöglich, der Mac sei untätig gewesen, obwohl er es nicht war.
Auch der umgekehrte Fall kommt vor. Das Bereinigen nach Aufbewahrungsdauer löscht alte Zeilen; die Löschung ist eine WAL-Transaktion, und die Hauptdatei behält die alten Zeilen bis zum nächsten Checkpoint. Beide Fälle sind nur sichtbar, wenn Sie beide Dateien haben und vergleichen.
Wie SQLite-WAL funktioniert
Maßgeblich ist die SQLite-Dokumentation zu Write-Ahead Logging und zum WAL-Dateiformat. Kurz gefasst: Die Datenbank besteht aus Seiten fester Größe. Im WAL-Modus ändert ein Schreibvorgang niemals Seiten direkt in der Hauptdatei. Er hängt neue Versionen der geänderten Seiten an die -wal-Datei an; Lesevorgänge suchen zuerst im WAL nach der neuesten festgeschriebenen Version einer Seite und greifen sonst auf die Hauptdatei zurück.
Der WAL-Header
Die -wal beginnt mit einem 32 Byte langen Header, Big-Endian:
| Offset | Größe | Feld |
|---|---|---|
| 0 | 4 | Magic: 0x377f0682 oder 0x377f0683 (legt die Bytereihenfolge der Prüfsumme fest) |
| 4 | 4 | Version des Dateiformats (3007000) |
| 8 | 4 | Seitengröße der Datenbank |
| 12 | 4 | Checkpoint-Sequenznummer |
| 16 | 4 | Salt-1 |
| 20 | 4 | Salt-2 |
| 24 | 8 | Prüfsumme über die ersten 24 Bytes |
Frames
Auf den Header folgen Frames: ein 24 Byte langer Frame-Header, gefolgt von einer vollständigen Seite.
| Offset | Größe | Feld |
|---|---|---|
| 0 | 4 | Seitennummer |
| 4 | 4 | Commit-Größe: beim letzten Frame einer Transaktion die Größe der Datenbank in Seiten nach dem Commit, sonst 0 |
| 8 | 4 | Salt-1, aus dem WAL-Header kopiert |
| 12 | 4 | Salt-2, aus dem WAL-Header kopiert |
| 16 | 8 | Kumulative Prüfsumme über den Header und alle Frames bis einschließlich diesem |
Welche Frames zählen
Ein Frame ist nur gültig, wenn seine Salts mit dem WAL-Header übereinstimmen und seine Prüfsumme der laufenden Prüfsumme entspricht, die vom Dateianfang an berechnet wird. Das Lesen endet beim ersten Frame, der eine der beiden Prüfungen nicht besteht. Unter den gültigen Frames gehören nur die bis zum letzten Commit-Frame (Commit-Größe ungleich null) zu festgeschriebenen Transaktionen. Frames danach bilden eine unvollendete Transaktion und werden von SQLite ignoriert; sie dürfen daher nicht als Datenbankinhalt behandelt werden. Taucht eine Seite in mehreren festgeschriebenen Frames auf, gilt der neueste.
Checkpoints und Zurücksetzen
Ein Checkpoint kopiert die neueste festgeschriebene Version jeder Seite aus dem WAL zurück in die Hauptdatei. Standardmäßig führt SQLite automatisch einen aus, wenn das WAL etwa 1000 Seiten erreicht, und normalerweise auch, wenn die letzte Verbindung zur Datenbank geschlossen wird. Nach einem Checkpoint kann der nächste Schreibvorgang das WAL von vorn beginnen: Salt-1 wird erhöht, Salt-2 ändert sich, und die Datei wird nicht unbedingt gekürzt. Frames der älteren Generation können daher hinter den gültigen erhalten bleiben. Ihre Salts passen nicht mehr, also ignoriert SQLite sie; es sind veraltete Seitenversionen, die nicht zur aktuellen Datenbank gehören.
Die -shm-Datei
knowledgeC.db-shm ist der WAL-Index: gemeinsam genutzter Speicher, der Verbindungen hilft, Seiten im WAL schnell zu finden. Sie enthält keine Daten, die nicht auch im WAL stehen, und lässt sich daraus neu aufbauen. Sichern Sie sie der Vollständigkeit halber mit den beiden anderen Dateien, der festgeschriebene Inhalt stammt aber aus der -wal.
Zwei Fälle, die eine Zeitleiste verändern
Zeilen, die nur im WAL stehen
Eine seit dem letzten Checkpoint eingefügte Zeile existiert nur als Seitenversion in der -wal. Werten Sie nur die Hauptdatei aus, fehlt die Zeile. Das sind typischerweise die neuesten Zeilen, die Lücke liegt also am Ende der Zeitleiste, unmittelbar vor der Sicherung.
Zeilen, die durch das WAL entfernt wurden
Ein festgeschriebenes DELETE erzeugt im WAL neue Seitenversionen ohne die Zeile. Die Hauptdatei enthält noch die alte Seite mit der Zeile. Liest man die Datenbank „so, wie SQLite es täte“, ist die Zeile verborgen; liest man nur die Hauptdatei, ist sie sichtbar. Der Vergleich beider Ansichten zeigt Ihnen, dass die Zeile existierte und nach dem letzten Checkpoint entfernt wurde.
Bei knowledgeC ist die übliche Ursache das Bereinigen alter Ereignisse nach Aufbewahrungsdauer. Eine durch das WAL entfernte Zeile ist für sich genommen kein Beleg für eine absichtliche Löschung; vergleichen Sie ihr Datum mit dem Aufbewahrungsfenster, das Sie am Beweismaterial gemessen haben, bevor Sie etwas hineinlesen. Direkt geänderte Zeilen behalten ihre Identität und zeigen einfach ihre neueren Werte.
Sicher arbeiten
- Öffnen Sie niemals das Original. Das Öffnen einer WAL-Datenbank mit einem normalen SQLite-Client kann einen Checkpoint auslösen: WAL-Seiten werden in die Hauptdatei geschrieben, und das WAL kann zurückgesetzt werden. Beide oben beschriebenen Fälle verschwinden dann.
- Bewahren Sie eine unveränderte Kopie auf. Hashen Sie die drei Dateien im gesicherten Zustand und werten Sie eine zweite Kopie aus.
- Wissen Sie, welche Ansicht Sie vor sich haben. Ein SQLite-Client, der beide Dateien erhält, zeigt die Datenbank mit angewendetem WAL und kann Ihre Kopie per Checkpoint verändern. Eine Kopie der Hauptdatei ohne ihre
-walzeigt den Stand beim letzten Checkpoint. Sie brauchen beide Ansichten, um zu sehen, was das WAL hinzugefügt und entfernt hat. - Dokumentieren Sie, was Ihnen fehlte. Wurde die
-walnicht gesichert, halten Sie das im Bericht fest: Das Fehlen aktueller Ereignisse ist dann eine Lücke in der Sicherung, kein Befund. Wie Sie sie sichern, steht in knowledgeC.db: Speicherort und Sicherung.
Wie KnowledgeC Parser das WAL verarbeitet
KnowledgeC Parser liest die Dateien schreibgeschützt in Ihrem Browser und ordnet jeder knowledgeC.db die gleichnamige -wal zu. Dann:
- prüft er den WAL-Header: Magic, Seitengröße gleich der Seitengröße der Datenbank, Header-Prüfsumme;
- liest er die Frames der Reihe nach, solange die Salts übereinstimmen und die laufende Prüfsumme korrekt ist, und stoppt beim ersten Fehler mit einem Hinweis wie „checksum mismatch at frame N“ oder „salt mismatch“;
- wendet er nur festgeschriebene Transaktionen an, vermerkt, wie viele Frames einer unvollendeten Transaktion ignoriert wurden, und legt die neueste festgeschriebene Version jeder Seite über die Hauptdatei;
- liest er
ZOBJECTzweimal, mit und ohne WAL, und gleicht die Zeilen über Datensatznummer und UUID ab.
Jedes knowledgeC-Ereignis trägt dann, wo relevant, eine von zwei Markierungen: only in the WAL (mit WAL vorhanden, in der Hauptdatei nicht) oder removed by the WAL (in der Hauptdatei vorhanden, durch eine festgeschriebene WAL-Transaktion gelöscht). Der Dateibericht fasst das Ergebnis als „WAL applied: N committed frame(s), X row(s) only in the WAL, Y row(s) removed by it“ zusammen. Kommt eine Datenbank im WAL-Modus ohne ihre -wal an, vermerkt der Bericht das und warnt, dass aktuelle Ereignisse fehlen könnten. Veraltete Frames aus älteren WAL-Generationen werden nicht verwendet.
Ein synthetisches Beispiel: FIN-MBP-03
Die mit dem Werkzeug ausgelieferte Beispielsammlung ist synthetisch; der Mac, die Benutzerin und die Ereignisse sind fiktiv. Auf dem MacBook FIN-MBP-03 enthält die Hauptdatei der System-knowledgeC.db Zeilen, die bis etwa 10:00 UTC am 2026-09-14 geschrieben wurden. Alles später Geschriebene steht in einer weiteren festgeschriebenen Transaktion im WAL.
Ohne die -wal ausgewertet, zeigt die Datenbank das letzte entsperrte Intervall von dana.whitlock an diesem Vormittag, das um 09:58 UTC endet, als sie den Mac zum Mittagessen sperrte, und danach nichts mehr. Mit ihr ausgewertet, meldet der Bericht „WAL applied“ mit einigen Dutzend Zeilen, die nur im WAL stehen, und einer, die durch das WAL entfernt wurde. Zu den Zeilen, die nur im WAL stehen, gehören:
- ein Entsperrintervall in
/device/isLocked, das um 10:04:31 UTC beginnt (ZSECONDSFROMGMT7200, also 12:04 Uhr Ortszeit) und um 10:49 UTC endet; - Intervalle in
/app/usagefür Safari, Finder, Archivierungsprogramm, Terminal und Systemeinstellungen innerhalb dieses Zeitfensters.
Die durch das WAL entfernte Zeile ist ein Intervall in /app/usage für com.apple.mail vom 2026-08-10: ein altes Ereignis, das durch das Bereinigen nach Aufbewahrungsdauer entfernt wurde und noch in der Hauptdatei steht. Es zeigt gut, warum „entfernt“ nicht als „gezielt gelöscht“ gelesen werden sollte.
Was das WAL hier hinzufügt, sind Existenz und Zeitpunkt von Aktivität während der Mittagspause. Es sagt nicht, wer an der Tastatur saß, und es nennt weder Dateien noch Befehle. Für diese Interpretation und für die Bestätigung durch Biome und andere Quellen lesen Sie wer saß an der Tastatur. Um das Beispiel nachzuvollziehen, laden Sie die Beispielsammlung von der Startseite oder folgen Sie knowledgeC und Biome im Browser analysieren.
Was das WAL Ihnen nicht sagt
- Wann ein Frame geschrieben wurde. Frames tragen keine Zeitstempel. Eine Zeile im WAL wurde nach dem letzten Checkpoint festgeschrieben; ihre Ereigniszeit stammt aus
ZSTARTDATEundZENDDATE, in Mac Absolute Time, nicht aus ihrer Position in der Datei. - Irgendetwas vor dem letzten Zurücksetzen. Veraltete Frames einer älteren Generation werden von SQLite und vom Werkzeug ignoriert; sie liegen außerhalb der aktuellen Datenbank.
- Was vor dem letzten Checkpoint gelöscht wurde. Ist eine Löschung per Checkpoint übertragen, fehlt die Zeile in beiden Ansichten; Reste im freien Speicher sind eine Frage des Carvings und liegen außerhalb dessen, was dieser Ablauf abdeckt.