Manutenzione Database
MongoDB Atlas
Monitoring via Grafana
Le metriche di MongoDB Atlas sono esposte tramite l'exporter mongodb-exporter e visibili nella dashboard Grafana MongoDB Overview:
# Connessioni attive per cluster
mongodb_ss_connections{conn_type="current"}
# Operazioni al secondo (per tipo)
rate(mongodb_ss_opcounters_total[5m])
# Latenza media operazioni
rate(mongodb_ss_opLatencies_latency_total[5m])
/ rate(mongodb_ss_opLatencies_ops_total[5m])
# Dimensione del working set vs RAM disponibile
mongodb_ss_mem_resident / mongodb_ss_mem_virtual
Gestione Indici
// Connessione al database di un tenant specifico
const db = client.db("t_ristorante_roma_01");
// Elencare tutti gli indici di una collection
db.orders.getIndexes();
// Verificare indici non utilizzati (da Atlas Performance Advisor)
// Oppure manualmente:
db.orders.aggregate([
{ $indexStats: {} },
{ $match: { "accesses.ops": { $lt: 10 } } } // Indici usati meno di 10 volte
]);
// Creare un indice in background (non blocca le operazioni)
db.orders.createIndex(
{ "status": 1, "createdAt": -1 },
{ background: true, name: "idx_status_createdAt" }
);
// Rimuovere un indice non utilizzato
db.orders.dropIndex("idx_vecchio_indice");
La creazione di indici su collection grandi (>1M documenti) puo richiedere minuti. Su Atlas M10+, gli indici vengono creati in background automaticamente, ma monitorare comunque le performance durante la creazione.
Compact e Repair
MongoDB Atlas non supporta compact direttamente. Per recuperare spazio disco:
- Atlas UI: Performance Advisor segnala collection frammentate
- Initial Sync: per frammentazione grave, eseguire un rolling initial sync dei nodi secondari tramite Atlas UI
- Collection rebuild: per casi estremi, creare una nuova collection e copiare i dati
// Verificare la frammentazione di una collection
const stats = db.orders.stats();
console.log(`Storage size: ${stats.storageSize}`);
console.log(`Data size: ${stats.size}`);
console.log(`Fragmentation ratio: ${1 - stats.size / stats.storageSize}`);
// Se ratio > 0.3, considerare compaction
Backup e Restore
MongoDB Atlas gestisce i backup automaticamente:
| Tipo | Frequenza | Retention | RPO |
|---|---|---|---|
| Continuous Backup | Continuo | 7 giorni (point-in-time) | ~1 secondo |
| Daily Snapshot | Ogni 24h | 30 giorni | 24 ore |
| Weekly Snapshot | Settimanale | 12 settimane | 7 giorni |
| Monthly Snapshot | Mensile | 12 mesi | 30 giorni |
# Restore point-in-time via Atlas CLI
atlas backups restores start pointInTime \
--clusterName pos-production \
--pointInTimeUTCSeconds $(date -d "2 hours ago" +%s) \
--targetClusterName pos-restore-temp \
--targetProjectId <project-id>
Archiviazione Cold Storage (S3)
I dati storici (ordini chiusi >6 mesi, log audit >1 anno) vengono archiviati su AWS S3:
// Procedura di archiviazione (eseguita dal scheduler mensile)
// 1. Estrarre documenti vecchi
const cutoffDate = new Date();
cutoffDate.setMonth(cutoffDate.getMonth() - 6);
const oldOrders = await db.orders.find({
status: { $in: ["completed", "cancelled"] },
closedAt: { $lt: cutoffDate }
}).toArray();
// 2. Scrivere su S3 in formato JSONL compresso
await s3.putObject({
Bucket: "impronto-archive",
Key: `tenants/${tenantId}/orders/${year}/${month}.jsonl.gz`,
Body: gzipStream(oldOrders),
StorageClass: "GLACIER_IR" // Instant Retrieval per accesso occasionale
});
// 3. Rimuovere dal database operativo
await db.orders.deleteMany({
_id: { $in: oldOrders.map(o => o._id) }
});
Connection Pool Monitoring
# Connessioni disponibili nel pool
pos_mongodb_pool_available
# Alert se pool quasi esaurito (< 10% disponibile)
pos_mongodb_pool_available / pos_mongodb_pool_size < 0.1
# Verificare le connessioni attive da MongoDB shell
db.serverStatus().connections
# { current: 45, available: 55, totalCreated: 1234 }
# Verificare da quale servizio vengono le connessioni
db.currentOp(true).inprog.filter(op => op.client).map(op => ({
client: op.client,
desc: op.desc,
secs_running: op.secs_running
}));
PostgreSQL DWH (Data Warehouse Analytics)
VACUUM e ANALYZE
PostgreSQL richiede manutenzione regolare per le tabelle del data warehouse:
-- VACUUM ANALYZE sulle tabelle principali (eseguire settimanalmente)
VACUUM ANALYZE fact_orders;
VACUUM ANALYZE fact_order_items;
VACUUM ANALYZE fact_payments;
VACUUM ANALYZE fact_cash_movements;
VACUUM ANALYZE dim_products;
VACUUM ANALYZE dim_tenants;
VACUUM ANALYZE dim_time;
-- VACUUM FULL per recuperare spazio (richiede lock esclusivo, pianificare in orario notturno)
VACUUM FULL fact_orders;
-- Verificare lo stato di autovacuum
SELECT schemaname, relname, last_vacuum, last_autovacuum,
n_dead_tup, n_live_tup,
ROUND(n_dead_tup::numeric / GREATEST(n_live_tup, 1) * 100, 2) AS dead_pct
FROM pg_stat_user_tables
WHERE schemaname = 'analytics'
ORDER BY n_dead_tup DESC
LIMIT 20;
Bloat delle Tabelle
-- Stimare il bloat (spazio sprecato) per tabella
SELECT
schemaname || '.' || tablename AS table_name,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size,
pg_size_pretty(pg_relation_size(schemaname || '.' || tablename)) AS table_size,
pg_size_pretty(pg_indexes_size(schemaname || '.' || tablename::regclass)) AS index_size
FROM pg_tables
WHERE schemaname = 'analytics'
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC
LIMIT 20;
ETL Pipeline Monitoring
L'ETL MongoDB -> PostgreSQL viene eseguito dal servizio scheduler ogni notte:
-- Verificare l'ultimo ETL completato
SELECT pipeline_name, started_at, completed_at,
rows_processed, status, error_message
FROM etl.pipeline_runs
ORDER BY started_at DESC
LIMIT 10;
-- Verificare gap nei dati (ordini mancanti)
SELECT date_key, COUNT(*) as order_count
FROM analytics.fact_orders
WHERE date_key >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY date_key
ORDER BY date_key;
Materialized View Refresh
Le dashboard Superset utilizzano materialized view per aggregazioni pre-calcolate:
-- Refresh delle materialized view (eseguire dopo ETL)
REFRESH MATERIALIZED VIEW CONCURRENTLY analytics.mv_daily_sales;
REFRESH MATERIALIZED VIEW CONCURRENTLY analytics.mv_product_performance;
REFRESH MATERIALIZED VIEW CONCURRENTLY analytics.mv_tenant_kpis;
-- Verificare quando e stato fatto l'ultimo refresh
SELECT schemaname, matviewname,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || matviewname)) AS size
FROM pg_matviews
WHERE schemaname = 'analytics';
-- Nota: CONCURRENTLY non blocca le letture ma richiede un indice UNIQUE
Redis Cloud
Gestione Memoria
# Informazioni memoria
redis-cli INFO memory
# used_memory_human: 245.67M
# maxmemory_human: 1.00G
# maxmemory_policy: allkeys-lru
# Distribuzione chiavi per pattern
redis-cli --scan --pattern "MOL-*" | head -20
# Conteggio chiavi per prefisso
redis-cli DBSIZE
Monitoraggio Redis Streams
Redis Streams e utilizzato per la coda eventi di sync:
# Lunghezza stream (numero messaggi pendenti)
redis-cli XLEN pos:sync:events
# Informazioni dettagliate sullo stream
redis-cli XINFO STREAM pos:sync:events
# length: 1234
# first-entry: ...
# last-entry: ...
# Consumer group status
redis-cli XINFO GROUPS pos:sync:events
# name: sync-workers
# consumers: 3
# pending: 45
# last-delivered-id: ...
# Messaggi pendenti (non acknowledged) per consumer
redis-cli XPENDING pos:sync:events sync-workers - + 10
# Claim messaggi bloccati (timeout > 5 minuti)
redis-cli XCLAIM pos:sync:events sync-workers worker-1 300000 <message-id>
Se XLEN cresce costantemente, i consumer non stanno processando abbastanza velocemente. Verificare:
- Numero di consumer attivi nel gruppo
- Errori nei log del servizio sync
- Latenza MongoDB (i consumer scrivono su MongoDB)
Key Expiry e TTL
# Verificare chiavi senza TTL (potenziale memory leak)
redis-cli --scan --pattern "MOL-*" | while read key; do
ttl=$(redis-cli TTL "$key")
if [ "$ttl" -eq "-1" ]; then
echo "NO TTL: $key"
fi
done
# Impostare TTL mancanti in bulk (usare con cautela)
# redis-cli EXPIRE "chiave" 3600
Schedule di Manutenzione
| Operazione | Frequenza | Finestra | Responsabile |
|---|---|---|---|
| MongoDB index review | Mensile | - | Dev team |
| MongoDB archivio S3 | Mensile | 02:00-04:00 domenica | Scheduler automatico |
| PostgreSQL VACUUM ANALYZE | Settimanale | 03:00-04:00 lunedi | Cron job |
| PostgreSQL VACUUM FULL | Trimestrale | 02:00-06:00 domenica | Manuale con manutenzione |
| Materialized view refresh | Giornaliero | Dopo ETL (~06:00) | Scheduler automatico |
| Redis memory review | Settimanale | - | Monitoring automatico |
| Redis Streams cleanup | Giornaliero | Automatico (MAXLEN) | Configurazione stream |
Riferimenti Incrociati
- Ottimizzazione delle Prestazioni - Tuning query e indici MongoDB
- Disaster Recovery e Backup - Procedure di restore
- Dashboard Grafana - Dashboard di monitoring database
- Troubleshooting Infrastrutturale - Problemi di connessione DB