Files
Charon/docs/database-maintenance.md
2026-03-04 18:34:49 +00:00

328 lines
8.5 KiB
Markdown

---
title: Database Maintenance
description: SQLite database maintenance guide for Charon. Covers backups, recovery, and troubleshooting database issues.
---
## Database Maintenance
Charon uses SQLite as its embedded database. This guide explains how the database
is configured, how to maintain it, and what to do if something goes wrong.
---
## Overview
### Why SQLite?
SQLite is perfect for Charon because:
- **Zero setup** — No external database server needed
- **Portable** — One file contains everything
- **Reliable** — Used by billions of devices worldwide
- **Fast** — Local file access beats network calls
### Where Is My Data?
| Environment | Database Location |
|-------------|-------------------|
| Docker | `/app/data/charon.db` |
| Local dev | `backend/data/charon.db` |
You may also see these files next to the database:
- `charon.db-wal` — Write-Ahead Log (temporary transactions)
- `charon.db-shm` — Shared memory file (temporary)
**Don't delete the WAL or SHM files while Charon is running!**
They contain pending transactions.
---
## Database Configuration
Charon automatically configures SQLite with optimized settings:
| Setting | Value | What It Does |
|---------|-------|--------------|
| `journal_mode` | WAL | Enables concurrent reads while writing |
| `busy_timeout` | 5000ms | Waits 5 seconds before failing on lock |
| `synchronous` | NORMAL | Balanced safety and speed |
| `cache_size` | 64MB | Memory cache for faster queries |
### What Is WAL Mode?
**WAL (Write-Ahead Logging)** is a more modern journaling mode for SQLite that:
- ✅ Allows readers while writing (no blocking)
- ✅ Faster for most workloads
- ✅ Reduces disk I/O
- ✅ Safer crash recovery
Charon enables WAL mode automatically — you don't need to do anything.
---
## Backups
### Automatic Backups
Charon creates automatic backups before destructive operations (like deleting hosts).
These are stored in:
| Environment | Backup Location |
|-------------|-----------------|
| Docker | `/app/data/backups/` |
| Local dev | `backend/data/backups/` |
### Manual Backups
To create a manual backup:
```bash
# Docker
docker exec charon cp /app/data/charon.db /app/data/backups/manual_backup.db
# Local development
cp backend/data/charon.db backend/data/backups/manual_backup.db
```
**Important:** If WAL mode is active, also copy the `-wal` and `-shm` files:
```bash
cp backend/data/charon.db-wal backend/data/backups/manual_backup.db-wal
cp backend/data/charon.db-shm backend/data/backups/manual_backup.db-shm
```
Or use the recovery script which handles this automatically (see below).
---
## Database Recovery
If your database becomes corrupted (rare, but possible after power loss or
disk failure), Charon includes a recovery script.
### When to Use Recovery
Use the recovery script if you see errors like:
- "database disk image is malformed"
- "database is locked" (persists after restart)
- "SQLITE_CORRUPT"
- Application won't start due to database errors
### Running the Recovery Script
**In Docker:**
```bash
# First, stop Charon to release database locks
docker stop charon
# Run recovery (from host)
docker run --rm -v charon_data:/app/data charon:latest /app/scripts/db-recovery.sh
# Restart Charon
docker start charon
```
**Local Development:**
```bash
# Make sure Charon is not running, then:
./scripts/db-recovery.sh
```
**Force mode (skip confirmations):**
```bash
./scripts/db-recovery.sh --force
```
### What the Recovery Script Does
1. **Creates a backup** — Saves your current database before any changes
2. **Runs integrity check** — Uses SQLite's `PRAGMA integrity_check`
3. **If healthy** — Confirms database is OK, enables WAL mode
4. **If corrupted** — Attempts automatic recovery:
- Exports data using SQLite `.dump` command
- Creates a new database from the dump
- Verifies the new database integrity
- Replaces the old database with the recovered one
5. **Cleans up** — Removes old backups (keeps last 10)
### Recovery Output Example
**Healthy database:**
```
==============================================
Charon Database Recovery Tool
==============================================
[INFO] sqlite3 found: 3.40.1
[INFO] Running in Docker environment
[INFO] Database path: /app/data/charon.db
[INFO] Creating backup: /app/data/backups/charon_backup_20250101_120000.db
[SUCCESS] Backup created successfully
==============================================
Integrity Check Results
==============================================
ok
[SUCCESS] Database integrity check passed!
[INFO] WAL mode already enabled
==============================================
Summary
==============================================
[SUCCESS] Database is healthy
[INFO] Backup stored at: /app/data/backups/charon_backup_20250101_120000.db
```
**Corrupted database (with successful recovery):**
```
==============================================
Integrity Check Results
==============================================
*** in database main ***
Page 42: btree page count invalid
[ERROR] Database integrity check FAILED
WARNING: Database corruption detected!
This script will attempt to recover the database.
A backup has already been created.
Continue with recovery? (y/N): y
==============================================
Recovery Process
==============================================
[INFO] Attempting database recovery...
[INFO] Exporting database via .dump command...
[SUCCESS] Database dump created
[INFO] Creating new database from dump...
[SUCCESS] Recovered database created
[SUCCESS] Recovered database passed integrity check
[INFO] Replacing original database with recovered version...
[SUCCESS] Database replaced successfully
==============================================
Summary
==============================================
[SUCCESS] Database recovery completed successfully!
[INFO] Please restart the Charon application
```
---
## Preventive Measures
### Do
-**Keep regular backups** — Use the backup page in Charon or manual copies
-**Use proper shutdown** — Stop Charon gracefully (`docker stop charon`)
-**Monitor disk space** — SQLite needs space for temporary files
-**Use reliable storage** — SSDs are more reliable than HDDs
### Don't
-**Don't kill Charon** — Avoid `docker kill` or `kill -9` (use `stop` instead)
-**Don't edit the database manually** — Unless you know SQLite well
-**Don't delete WAL files** — While Charon is running
-**Don't run out of disk space** — Can cause corruption
---
## Troubleshooting
### "Database is locked"
**Cause:** Another process has the database open.
**Fix:**
1. Stop all Charon instances
2. Check for zombie processes: `ps aux | grep charon`
3. Kill any remaining processes
4. Restart Charon
### "Database disk image is malformed"
**Cause:** Database corruption (power loss, disk failure, etc.)
**Fix:**
1. Stop Charon
2. Run the recovery script: `./scripts/db-recovery.sh`
3. Restart Charon
### "SQLITE_BUSY"
**Cause:** Long-running transaction blocking others.
**Fix:** Usually resolves itself (5-second timeout). If persistent:
1. Restart Charon
2. If still occurring, check for stuck processes
### WAL File Is Very Large
**Cause:** Many writes without checkpointing.
**Fix:** This is usually handled automatically. To force a checkpoint:
```bash
sqlite3 /path/to/charon.db "PRAGMA wal_checkpoint(TRUNCATE);"
```
### Lost Data After Recovery
**What happened:** The `.dump` command recovers readable data, but severely
corrupted records may be lost.
**What to do:**
1. Check your automatic backups in `data/backups/`
2. Restore from the most recent pre-corruption backup
3. Re-create any missing configuration manually
---
## Advanced: Manual Recovery
If the automatic script fails, you can try manual recovery:
```bash
# 1. Create a SQL dump of whatever is readable
sqlite3 charon.db ".dump" > backup.sql
# 2. Check what was exported
head -100 backup.sql
# 3. Create a new database
sqlite3 charon_new.db < backup.sql
# 4. Verify the new database
sqlite3 charon_new.db "PRAGMA integrity_check;"
# 5. If OK, replace the old database
mv charon.db charon_corrupted.db
mv charon_new.db charon.db
# 6. Enable WAL mode on the new database
sqlite3 charon.db "PRAGMA journal_mode=WAL;"
```
---
## Need Help?
If recovery fails or you're unsure what to do:
1. **Don't panic** — Your backup was created before recovery attempts
2. **Check backups** — Look in `data/backups/` for recent copies
3. **Ask for help** — Open an issue on [GitHub](https://github.com/Wikid82/charon/issues)
with your error messages