Skip to main content

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");
Indici in Produzione

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:

  1. Atlas UI: Performance Advisor segnala collection frammentate
  2. Initial Sync: per frammentazione grave, eseguire un rolling initial sync dei nodi secondari tramite Atlas UI
  3. 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:

TipoFrequenzaRetentionRPO
Continuous BackupContinuo7 giorni (point-in-time)~1 secondo
Daily SnapshotOgni 24h30 giorni24 ore
Weekly SnapshotSettimanale12 settimane7 giorni
Monthly SnapshotMensile12 mesi30 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>
XLEN Crescente

Se XLEN cresce costantemente, i consumer non stanno processando abbastanza velocemente. Verificare:

  1. Numero di consumer attivi nel gruppo
  2. Errori nei log del servizio sync
  3. 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

OperazioneFrequenzaFinestraResponsabile
MongoDB index reviewMensile-Dev team
MongoDB archivio S3Mensile02:00-04:00 domenicaScheduler automatico
PostgreSQL VACUUM ANALYZESettimanale03:00-04:00 lunediCron job
PostgreSQL VACUUM FULLTrimestrale02:00-06:00 domenicaManuale con manutenzione
Materialized view refreshGiornalieroDopo ETL (~06:00)Scheduler automatico
Redis memory reviewSettimanale-Monitoring automatico
Redis Streams cleanupGiornalieroAutomatico (MAXLEN)Configurazione stream

Riferimenti Incrociati

Questa pagina ti è stata utile?