4.8 KiB
4.8 KiB
DB Repair Playbook
Symptome einer korrupten DB
POST /api/sync/push→ 500, Server-Log zeigtSqliteError: database disk image is malformedGET /api/admin/integrity→{ ok: false, result: "..." }- Startup-Log:
[db] integrity_check failed:
Ursachen
- Azure App Service hat Container während eines laufenden SQLite-Writes neugestartet
- WAL-Datei (
ka-note.db-wal) war nicht committed beim Neustart - Hinweis: WAL-Mode ist aktiv (
journal_mode = WAL) — schützt vor vielen, aber nicht allen Szenarien
Schritt 1: Integrität prüfen
GET /api/admin/integrity
→ { ok: true/false, result: "ok" | "<Fehlermeldung>" }
Oder lokal nach DB-Download:
.\sqlite3.exe ka-note.db "PRAGMA integrity_check;"
Schritt 2: DB herunterladen (Kudu REST API)
Deployment-Credentials aus Portal: App Service → Deployment Center → FTPS credentials
$user = 'ka-note\$ka-note' # anpassen
$pass = 'deinPassword'
$creds = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${user}:${pass}"))
Invoke-WebRequest `
-Uri "https://ka-note.scm.azurewebsites.net/api/vfs/data/ka-note.db" `
-Headers @{ Authorization = "Basic $creds" } `
-OutFile "ka-note.db"
(Get-Item "ka-note.db").Length # muss > 0 sein
sqlite3.exe herunterladen von https://www.sqlite.org/download.html (sqlite-tools-win-x64-*.zip)
Schritt 3: DB reparieren
# 1. Dump erzeugen
.\sqlite3.exe ka-note.db ".dump" > dump.sql
# 2. Doppelte INSERT-Konflikte entschärfen + ROLLBACK→COMMIT
(Get-Content dump.sql) -replace '^INSERT INTO', 'INSERT OR IGNORE INTO' | Set-Content dump-fixed.sql
# 3. unistr()-Calls dekodieren (nötig wenn Server neueres SQLite als lokal)
node fix-unistr.js # siehe unten
# 4. Importieren
# NICHT cmd /c — sqlite3 ist nicht im cmd.exe PATH, schlägt still fehl (0-Byte DB)
# bash stdin redirect funktioniert zuverlässig:
sqlite3 ka-note-repaired.db < dump-fixed2.sql
# 5. Integrität prüfen
.\sqlite3.exe ka-note-repaired.db "PRAGMA integrity_check;"
.\sqlite3.exe ka-note-repaired.db ".tables"
.\sqlite3.exe ka-note-repaired.db "SELECT COUNT(*) FROM contexts; SELECT COUNT(*) FROM topics; SELECT COUNT(*) FROM history_entries;"
fix-unistr.js (im sqlite-Arbeitsverzeichnis ablegen)
Wichtig: Script nie per Shell-Heredoc schreiben — bash/PowerShell mangeln Regex-Backslashes. Stattdessen: Write-Tool (Claude) oder Editor verwenden.
import { readFileSync, writeFileSync } from 'fs';
let sql = readFileSync('dump-fixed.sql', 'utf8');
// unistr('\uXXXX') → plain UTF-8 string
sql = sql.replace(/unistr\('((?:[^'\\]|\\.)*)'\)/g, (_, inner) => {
const decoded = inner.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) =>
String.fromCharCode(parseInt(hex, 16))
);
return `'${decoded}'`;
});
// ROLLBACK at end of corrupt dump → COMMIT so import doesn't discard everything
sql = sql.replace(/^ROLLBACK;.*$/m, 'COMMIT;');
writeFileSync('dump-fixed2.sql', sql, 'utf8');
console.log('done');
Kritisch: Ein korrupter Dump endet mit ROLLBACK; -- due to errors statt COMMIT;.
SQLite verwirft dann die gesamte Transaktion → 0-Byte-Zieldatei.
Das Script ersetzt ROLLBACK durch COMMIT.
Schritt 4: Reparierte DB hochladen
# App stoppen (DB darf nicht aktiv sein)
az webapp stop --name ka-note --resource-group <RG>
# Hochladen
Invoke-RestMethod `
-Uri "https://ka-note.scm.azurewebsites.net/api/vfs/data/ka-note.db" `
-Method PUT `
-Headers @{ Authorization = "Basic $creds"; "Content-Type" = "application/octet-stream" } `
-InFile "ka-note-repaired.db"
# App starten
az webapp start --name ka-note --resource-group <RG>
Schritt 5: Verifizieren
GET /api/admin/integrity → { ok: true }
GET /api/sync/status → Anzahl contexts/topics/history_entries prüfen
Präventionsmaßnahmen (umgesetzt)
- WAL-Mode (
journal_mode = WAL) — aktiv seit Beginn, schützt vor den meisten Write-Crashes - Integrity-Check beim Start —
[db] integrity_check okim Startup-Log sichtbar - Integrity-Check vor Backup — korrupte DB wird nicht als Backup gespeichert, Fehler im Log
GET /api/admin/integrity— on-demand prüfbar ohne Server-Zugriff- Structured Error Logging — alle Route-Handler loggen Fehler mit Label, Method, Path, Stack
Bekannte Fallstricke
| Problem | Ursache | Lösung |
|---|---|---|
| Download → 0 Byte | Falscher Pfad oder Auth | Pfad mit /api/vfs/data/ prüfen |
| Import → 0 Byte | sqlite3 nicht im cmd.exe PATH | bash stdin redirect: sqlite3 db.db < file |
unistr() Fehler |
Versionsunterschied sqlite3 | fix-unistr.js ausführen |
| UNIQUE constraint | Doppelte Rows aus Korruption | INSERT OR IGNORE in dump-fixed.sql |
| Alles verworfen | Dump endet mit ROLLBACK | ROLLBACK → COMMIT ersetzen (fix-unistr.js macht das) |