docs: Add detailed example workflow
This commit is contained in:
400
EXAMPLE_WORKFLOW.md
Normal file
400
EXAMPLE_WORKFLOW.md
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
# Example Complete Workflow
|
||||||
|
|
||||||
|
Un esempio passo-passo di come usare il tool per una migrazione completa.
|
||||||
|
|
||||||
|
## Scenario
|
||||||
|
|
||||||
|
Devi migrare il database MySQL `production_db` a PostgreSQL, incluso setup del container Incus e test di performance.
|
||||||
|
|
||||||
|
### Dati
|
||||||
|
- RAWDATACOR: ~50 milioni di righe (5 anni di dati)
|
||||||
|
- ELABDATADISP: ~25 milioni di righe
|
||||||
|
|
||||||
|
### Timeline
|
||||||
|
- Tempo disponibile: 2 ore per migrazione
|
||||||
|
- Test: 30 minuti
|
||||||
|
- Validazione: 30 minuti
|
||||||
|
|
||||||
|
## Step-by-Step Workflow
|
||||||
|
|
||||||
|
### 1. Preparazione (10 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clonare il progetto
|
||||||
|
cd /home/user/projects
|
||||||
|
git clone <repo> mysql2postgres
|
||||||
|
cd mysql2postgres
|
||||||
|
|
||||||
|
# Setup Python
|
||||||
|
./install.sh
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
# Verificare Python
|
||||||
|
python --version
|
||||||
|
# Output: Python 3.10.x
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Setup Container PostgreSQL (10 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Creare e configurare container Incus
|
||||||
|
bash scripts/incus_setup.sh pg-prod password123
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# ✓ PostgreSQL is running!
|
||||||
|
#
|
||||||
|
# Connection details:
|
||||||
|
# Host: 10.100.50.123
|
||||||
|
# Port: 5432
|
||||||
|
# User: postgres
|
||||||
|
# Password: password123
|
||||||
|
#
|
||||||
|
# Update .env file with:
|
||||||
|
# POSTGRES_HOST=10.100.50.123
|
||||||
|
# POSTGRES_PASSWORD=password123
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Configurazione (5 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copiare template e editare
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env
|
||||||
|
|
||||||
|
# Configurazione finale:
|
||||||
|
# MYSQL_HOST=db.production.com
|
||||||
|
# MYSQL_PORT=3306
|
||||||
|
# MYSQL_USER=migration_user
|
||||||
|
# MYSQL_PASSWORD=secure_password
|
||||||
|
# MYSQL_DATABASE=production_db
|
||||||
|
#
|
||||||
|
# POSTGRES_HOST=10.100.50.123
|
||||||
|
# POSTGRES_PORT=5432
|
||||||
|
# POSTGRES_USER=postgres
|
||||||
|
# POSTGRES_PASSWORD=password123
|
||||||
|
# POSTGRES_DATABASE=production_migrated
|
||||||
|
#
|
||||||
|
# BATCH_SIZE=50000 # Large batches for speed
|
||||||
|
# LOG_LEVEL=INFO
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Verifica Configurazione (5 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py info
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# [MySQL Configuration]
|
||||||
|
# Host: db.production.com:3306
|
||||||
|
# Database: production_db
|
||||||
|
# User: migration_user
|
||||||
|
#
|
||||||
|
# [PostgreSQL Configuration]
|
||||||
|
# Host: 10.100.50.123:5432
|
||||||
|
# Database: production_migrated
|
||||||
|
# User: postgres
|
||||||
|
#
|
||||||
|
# [Migration Settings]
|
||||||
|
# Batch Size: 50000
|
||||||
|
# Log Level: INFO
|
||||||
|
# Dry Run: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Setup Schema PostgreSQL (5 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Creare schema con partizioni e indici
|
||||||
|
python main.py setup --create-schema
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# Connected to PostgreSQL: 10.100.50.123:5432/production_migrated
|
||||||
|
# Creating PostgreSQL schema...
|
||||||
|
# ✓ Schema creation complete
|
||||||
|
# ✓ PostgreSQL schema created successfully
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Verifica Connessione MySQL (2 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fare una query test MySQL
|
||||||
|
python -c "
|
||||||
|
from src.connectors.mysql_connector import MySQLConnector
|
||||||
|
with MySQLConnector() as conn:
|
||||||
|
count = conn.get_row_count('RAWDATACOR')
|
||||||
|
print(f'RAWDATACOR: {count:,} rows')
|
||||||
|
count = conn.get_row_count('ELABDATADISP')
|
||||||
|
print(f'ELABDATADISP: {count:,} rows')
|
||||||
|
"
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# RAWDATACOR: 50,234,567 rows
|
||||||
|
# ELABDATADISP: 25,789,123 rows
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Dry-Run Migration (Opzionale, 10 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Testare senza modificare i dati
|
||||||
|
python main.py migrate full --dry-run
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# [DRY RUN] Would migrate all rows
|
||||||
|
# ✓ Migration complete: 50234567 rows migrated to rawdatacor
|
||||||
|
# ✓ RAWDATACOR: 50234567 rows migrated
|
||||||
|
# [DRY RUN] Would migrate all rows
|
||||||
|
# ✓ Migration complete: 25789123 rows migrated to elabdatadisp
|
||||||
|
# ✓ ELABDATADISP: 25789123 rows migrated
|
||||||
|
# ✓ Full migration complete: 76023690 total rows migrated
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. Migrazione Completa (60 min per dati grandi)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lanciare la migrazione vera
|
||||||
|
python main.py migrate full
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# Migrating RAWDATACOR...
|
||||||
|
# Migrating RAWDATACOR ██████████████░░░░░░░░░░░░░░░░░░░░░░░░ 35% 00:42:15
|
||||||
|
# ✓ RAWDATACOR: 50234567 rows migrated
|
||||||
|
#
|
||||||
|
# Migrating ELABDATADISP...
|
||||||
|
# Migrating ELABDATADISP ████████████████████████████████░░░░░░░░░░ 75% 00:15:30
|
||||||
|
# ✓ ELABDATADISP: 25789123 rows migrated
|
||||||
|
#
|
||||||
|
# ✓ Full migration complete: 76023690 total rows migrated
|
||||||
|
|
||||||
|
# ⏱ Timing per RAWDATACOR:
|
||||||
|
# - 50M rows
|
||||||
|
# - 50k batch size = 1000 transazioni
|
||||||
|
# - ~3 sec per batch
|
||||||
|
# - Total: ~50 minuti
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9. Validazione Dati (15 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Connettere a PostgreSQL e validare
|
||||||
|
psql -h 10.100.50.123 -U postgres -d production_migrated
|
||||||
|
|
||||||
|
# SQL validation queries
|
||||||
|
postgres=# SELECT COUNT(*) FROM rawdatacor;
|
||||||
|
# count: 50234567
|
||||||
|
|
||||||
|
postgres=# SELECT COUNT(*) FROM elabdatadisp;
|
||||||
|
# count: 25789123
|
||||||
|
|
||||||
|
postgres=# SELECT event_date, COUNT(*) FROM rawdatacor GROUP BY event_date ORDER BY event_date LIMIT 10;
|
||||||
|
# Verificare distribuzione date
|
||||||
|
|
||||||
|
postgres=# SELECT measurements FROM rawdatacor WHERE measurements IS NOT NULL LIMIT 1 \gx
|
||||||
|
# Verificare struttura JSONB
|
||||||
|
|
||||||
|
# Esecuzione script validazione
|
||||||
|
\i scripts/validate_migration.sql
|
||||||
|
|
||||||
|
# Controllare:
|
||||||
|
# - Row counts match
|
||||||
|
# - No NULL measurements
|
||||||
|
# - Date ranges correct
|
||||||
|
# - Indexes created
|
||||||
|
# - Partitions exist
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10. Benchmark Performance (30 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Eseguire benchmark con 10 iterazioni
|
||||||
|
python main.py benchmark --iterations 10 --output production_benchmark.json
|
||||||
|
|
||||||
|
# Output example:
|
||||||
|
# Running performance benchmarks...
|
||||||
|
#
|
||||||
|
# [RAWDATACOR]
|
||||||
|
# select_by_pk:
|
||||||
|
# MySQL: 0.45ms (min: 0.35ms, max: 0.65ms)
|
||||||
|
# PostgreSQL: 0.32ms (min: 0.28ms, max: 0.38ms)
|
||||||
|
# ✓ PostgreSQL is 1.4x faster
|
||||||
|
#
|
||||||
|
# select_by_date_range:
|
||||||
|
# MySQL: 125.50ms (min: 120.00ms, max: 135.00ms)
|
||||||
|
# PostgreSQL: 45.20ms (min: 42.00ms, max: 50.00ms)
|
||||||
|
# ✓ PostgreSQL is 2.8x faster
|
||||||
|
#
|
||||||
|
# jsonb_filter_value:
|
||||||
|
# PostgreSQL: 32.10ms (min: 28.00ms, max: 38.00ms)
|
||||||
|
# (MySQL non supporta JSONB)
|
||||||
|
#
|
||||||
|
# [ELABDATADISP]
|
||||||
|
# ...
|
||||||
|
#
|
||||||
|
# ✓ Benchmark complete: results saved to benchmark_results/benchmark_20240115_143022.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11. Analizzare Risultati Benchmark
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Visualizzare JSON results
|
||||||
|
cat production_benchmark.json | python -m json.tool
|
||||||
|
|
||||||
|
# Risultati attesi:
|
||||||
|
# - SELECT semplici: PostgreSQL 2-3x più veloce
|
||||||
|
# - Range query: PostgreSQL 2-4x più veloce
|
||||||
|
# - JSONB query: Solo PostgreSQL (non disponibili in MySQL)
|
||||||
|
# - Aggregazioni: PostgreSQL simile o migliore
|
||||||
|
|
||||||
|
# Interpretazione:
|
||||||
|
# - RAWDATACOR con JSONB: beneficio 30-50% (meno colonne in storage)
|
||||||
|
# - ELABDATADISP con JSONB: beneficio 20-30% (compressione dei NULL)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 12. Setup Migrazioni Incrementali (5 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Configurare cron per sincronizzazione periodica
|
||||||
|
bash scripts/setup_cron.sh
|
||||||
|
|
||||||
|
# Quando viene chiesto se aggiungere il cron:
|
||||||
|
# Aggiunge:
|
||||||
|
# 0 */6 * * * cd /path/to/mysql2postgres && python main.py migrate incremental >> migration_*.log 2>&1
|
||||||
|
#
|
||||||
|
# Risultato: esecuzione ogni 6 ore
|
||||||
|
|
||||||
|
# Verificare
|
||||||
|
crontab -l | grep migrate
|
||||||
|
# Output: 0 */6 * * * cd /home/user/projects/mysql2postgres && ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 13. Primo Test Migrazioni Incrementali (5 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Simulare cambiamenti in MySQL
|
||||||
|
# (aggiungere alcuni record nuovi)
|
||||||
|
|
||||||
|
# Poi eseguire migrazione incrementale
|
||||||
|
python main.py migrate incremental
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# Incremental migration for RAWDATACOR...
|
||||||
|
# ℹ RAWDATACOR: 0 rows migrated
|
||||||
|
#
|
||||||
|
# Incremental migration for ELABDATADISP...
|
||||||
|
# ℹ ELABDATADISP: 0 rows migrated
|
||||||
|
#
|
||||||
|
# ℹ No rows to migrate
|
||||||
|
|
||||||
|
# Oppure se ci sono dati:
|
||||||
|
# Incremental migration for RAWDATACOR...
|
||||||
|
# ✓ RAWDATACOR: 1234 rows migrated
|
||||||
|
#
|
||||||
|
# ✓ Incremental migration complete: 1234 total rows migrated
|
||||||
|
```
|
||||||
|
|
||||||
|
## Risultati Attesi
|
||||||
|
|
||||||
|
### Tempo Totale
|
||||||
|
- Setup: 30 minuti
|
||||||
|
- Migrazione: 60-90 minuti (dipende da dimensione)
|
||||||
|
- Test: 30 minuti
|
||||||
|
- **Totale: 2-3 ore**
|
||||||
|
|
||||||
|
### Performance Gains
|
||||||
|
- Storage: 10-20% riduzione (JSONB compressione)
|
||||||
|
- Query tempo: 2-4x più veloce su PostgreSQL
|
||||||
|
- Indici: più efficienti con JSONB GIN
|
||||||
|
|
||||||
|
### Validazione
|
||||||
|
- Row counts: Match 100%
|
||||||
|
- Date ranges: Completi
|
||||||
|
- JSONB structure: Valida
|
||||||
|
- Indexes: Tutti creati
|
||||||
|
- Partitions: Funzionanti
|
||||||
|
|
||||||
|
## Troubleshooting Durante Workflow
|
||||||
|
|
||||||
|
### Errore: "Cannot connect to MySQL"
|
||||||
|
```bash
|
||||||
|
# Verificare credenziali
|
||||||
|
mysql -h db.production.com -u migration_user -p -e "SELECT 1" < /dev/null
|
||||||
|
|
||||||
|
# Verificare firewall
|
||||||
|
nc -zv db.production.com 3306
|
||||||
|
|
||||||
|
# Controllare .env
|
||||||
|
grep MYSQL .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Errore: "Schema creation failed"
|
||||||
|
```bash
|
||||||
|
# Verificare PostgreSQL online
|
||||||
|
psql -h 10.100.50.123 -U postgres -c "SELECT version()"
|
||||||
|
|
||||||
|
# Recreate schema
|
||||||
|
python main.py setup --create-schema
|
||||||
|
```
|
||||||
|
|
||||||
|
### Migrazione molto lenta
|
||||||
|
```bash
|
||||||
|
# Aumentare batch size temporaneamente
|
||||||
|
# Editare .env: BATCH_SIZE=100000
|
||||||
|
|
||||||
|
# Oppure verificare:
|
||||||
|
# - Latency rete MySQL↔PostgreSQL
|
||||||
|
# - CPU/Memoria su entrambi i server
|
||||||
|
# - Disk I/O disponibile
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoraggio Durante Migrazione
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In un altro terminale, monitorare progresso
|
||||||
|
watch "ps aux | grep -i 'python main.py'"
|
||||||
|
|
||||||
|
# Oppure monitorare database
|
||||||
|
# PostgreSQL
|
||||||
|
psql -h 10.100.50.123 -U postgres -d production_migrated \
|
||||||
|
-c "SELECT COUNT(*) FROM rawdatacor"
|
||||||
|
|
||||||
|
# MySQL
|
||||||
|
mysql -h db.production.com -u migration_user -p production_db \
|
||||||
|
-e "SELECT COUNT(*) FROM RAWDATACOR"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Post-Migration Checklist
|
||||||
|
|
||||||
|
- [ ] Row counts match MySQL e PostgreSQL
|
||||||
|
- [ ] Date ranges sono completi
|
||||||
|
- [ ] JSONB structure è valido
|
||||||
|
- [ ] Indici sono stati creati
|
||||||
|
- [ ] Query critiche funzionano su PostgreSQL
|
||||||
|
- [ ] Benchmark mostra improvement
|
||||||
|
- [ ] Cron job per incremental è configurato
|
||||||
|
- [ ] Backups dei dati migration sono salvati
|
||||||
|
- [ ] Log di migrazione sono archiviati
|
||||||
|
|
||||||
|
## Documenti da Archiviare
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Creare directory backup
|
||||||
|
mkdir -p backups/migration_$(date +%Y%m%d)
|
||||||
|
|
||||||
|
# Salvare:
|
||||||
|
# - benchmark results
|
||||||
|
# - migration logs
|
||||||
|
# - .env file (con password rimossa)
|
||||||
|
# - validation output
|
||||||
|
# - timing reports
|
||||||
|
|
||||||
|
cp production_benchmark.json backups/migration_*/
|
||||||
|
cp *.log backups/migration_*/ 2>/dev/null || true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Successo!
|
||||||
|
|
||||||
|
Quando tutto è completato:
|
||||||
|
|
||||||
|
✓ Dati migrati completamente
|
||||||
|
✓ Performance validata (PostgreSQL più veloce)
|
||||||
|
✓ JSONB schema funzionante
|
||||||
|
✓ Migrazioni incrementali configurate
|
||||||
|
✓ Pronto per switchover produzione
|
||||||
Reference in New Issue
Block a user