Ka-Note/docs/feature-dbrepair.md

135 lines
4.8 KiB
Markdown

# DB Repair Playbook
## Symptome einer korrupten DB
- `POST /api/sync/push` → 500, Server-Log zeigt `SqliteError: database disk image is malformed`
- `GET /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:
```cmd
.\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**
```powershell
$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
```powershell
# 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.
```js
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
```powershell
# 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 ok` im 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) |