170 lines
4.4 KiB
Markdown
170 lines
4.4 KiB
Markdown
# Runbook: Database Down / DB Pool Exhausted
|
||
|
||
## Signal
|
||
|
||
**Alertes déclenchées**:
|
||
- `VezaDBPoolHighUsage` - DB pool > 80% (20/25 connexions)
|
||
- `VezaDBPoolExhausted` - DB pool épuisé (wait count augmente)
|
||
- `/readyz` retourne `503 Service Unavailable` avec `status: "not_ready"`
|
||
|
||
**Symptômes observables**:
|
||
- Erreurs 5xx sur endpoints nécessitant la DB
|
||
- Logs: `database connection failed`, `connection pool exhausted`
|
||
- Métriques: `veza_db_pool_open_connections` proche de 25, `veza_db_pool_wait_count_total` augmente
|
||
|
||
## Hypothèses
|
||
|
||
1. **DB down** - PostgreSQL ne répond plus
|
||
2. **DB pool saturé** - Trop de connexions ouvertes, pool épuisé
|
||
3. **Réseau** - Problème de connectivité entre app et DB
|
||
4. **DB lente** - Requêtes bloquantes, connexions non libérées
|
||
|
||
## Vérifications
|
||
|
||
### 1. Vérifier l'état de la DB
|
||
|
||
```bash
|
||
# Depuis le serveur DB
|
||
sudo systemctl status postgresql
|
||
# ou
|
||
docker ps | grep postgres
|
||
|
||
# Tester connexion directe
|
||
psql -h localhost -U veza -d veza_db -c "SELECT 1;"
|
||
```
|
||
|
||
### 2. Vérifier métriques Prometheus
|
||
|
||
```bash
|
||
# Pool connexions
|
||
curl -s http://localhost:9090/api/v1/query?query=veza_db_pool_open_connections
|
||
|
||
# Wait count (doit être stable, pas augmenter)
|
||
curl -s http://localhost:9090/api/v1/query?query=rate(veza_db_pool_wait_count_total[5m])
|
||
|
||
# Connexions en cours d'utilisation
|
||
curl -s http://localhost:9090/api/v1/query?query=veza_db_pool_in_use
|
||
```
|
||
|
||
### 3. Vérifier logs application
|
||
|
||
```bash
|
||
# Chercher erreurs DB
|
||
grep -i "database\|connection\|pool" /var/log/veza-backend-api/*.log | tail -50
|
||
|
||
# Chercher requêtes lentes (si logging activé)
|
||
grep "slow query" /var/log/veza-backend-api/*.log
|
||
```
|
||
|
||
### 4. Vérifier connexions actives DB
|
||
|
||
```sql
|
||
-- Depuis psql
|
||
SELECT count(*) FROM pg_stat_activity WHERE datname = 'veza_db';
|
||
SELECT pid, usename, application_name, state, query_start, query
|
||
FROM pg_stat_activity
|
||
WHERE datname = 'veza_db'
|
||
ORDER BY query_start;
|
||
```
|
||
|
||
## Actions Correctives
|
||
|
||
### Si DB down
|
||
|
||
1. **Redémarrer PostgreSQL**:
|
||
```bash
|
||
sudo systemctl restart postgresql
|
||
# ou
|
||
docker restart veza-postgres
|
||
```
|
||
|
||
2. **Vérifier logs PostgreSQL**:
|
||
```bash
|
||
tail -100 /var/log/postgresql/postgresql-*.log
|
||
# ou
|
||
docker logs veza-postgres --tail 100
|
||
```
|
||
|
||
3. **Vérifier espace disque**:
|
||
```bash
|
||
df -h /var/lib/postgresql
|
||
```
|
||
|
||
4. **Vérifier mémoire**:
|
||
```bash
|
||
free -h
|
||
```
|
||
|
||
### Si DB pool saturé
|
||
|
||
1. **Identifier requêtes bloquantes**:
|
||
```sql
|
||
SELECT pid, usename, application_name, state, wait_event_type, wait_event, query_start, query
|
||
FROM pg_stat_activity
|
||
WHERE datname = 'veza_db' AND state != 'idle'
|
||
ORDER BY query_start;
|
||
```
|
||
|
||
2. **Tuer requêtes bloquantes** (si nécessaire):
|
||
```sql
|
||
SELECT pg_terminate_backend(pid)
|
||
FROM pg_stat_activity
|
||
WHERE datname = 'veza_db'
|
||
AND state = 'active'
|
||
AND query_start < NOW() - INTERVAL '5 minutes';
|
||
```
|
||
|
||
3. **Augmenter pool temporairement** (si configurable):
|
||
- Modifier `internal/config/config.go:446` (MaxOpenConns)
|
||
- Redémarrer application
|
||
- **⚠️ Attention**: Augmenter le pool peut masquer le problème réel
|
||
|
||
4. **Vérifier connexions non fermées**:
|
||
- Auditer code pour `defer db.Close()` manquants
|
||
- Vérifier transactions non commitées/rollbackées
|
||
|
||
### Si réseau
|
||
|
||
1. **Tester connectivité**:
|
||
```bash
|
||
telnet <DB_HOST> 5432
|
||
# ou
|
||
nc -zv <DB_HOST> 5432
|
||
```
|
||
|
||
2. **Vérifier firewall**:
|
||
```bash
|
||
sudo iptables -L -n | grep 5432
|
||
```
|
||
|
||
3. **Vérifier DNS**:
|
||
```bash
|
||
nslookup <DB_HOST>
|
||
```
|
||
|
||
## Post-Mortem Notes
|
||
|
||
### À documenter après résolution
|
||
|
||
- **Cause racine**: DB down / Pool saturé / Réseau / Autre
|
||
- **Durée de l'incident**: De [heure début] à [heure fin]
|
||
- **Impact**: Endpoints affectés, utilisateurs impactés
|
||
- **Actions prises**: Liste des actions correctives
|
||
- **Actions préventives**:
|
||
- [ ] Augmenter monitoring DB pool
|
||
- [ ] Ajouter alertes sur requêtes lentes
|
||
- [ ] Auditer code pour connexions non fermées
|
||
- [ ] Configurer connection pooling côté DB (PgBouncer)
|
||
|
||
### Métriques à surveiller post-incident
|
||
|
||
- `veza_db_pool_open_connections` - Doit rester < 20
|
||
- `veza_db_pool_wait_count_total` - Doit rester stable
|
||
- `veza_db_pool_in_use` - Doit être < `open_connections`
|
||
- `/readyz` - Doit retourner `200 ready`
|
||
|
||
## Références
|
||
|
||
- Configuration DB pool: `internal/config/config.go:446` (MaxOpenConns: 25)
|
||
- Health check: `internal/handlers/health.go:124-140`
|
||
- Métriques DB: `internal/metrics/db_pool.go`
|