2010-08-13 18 views
13

Ho bisogno di migrare un progetto complesso da sqlite a PostgreSQL. Un sacco di gente sembra avere problemi con chiavi esterne, truncature dati e così via ...Django: Quali sono le migliori pratiche per migrare un progetto da sqlite a PosgreSQL

  • C'è un programma di utilità completo automatizzato?
  • Devo controllare alcuni dati o schema prima della migrazione?

Edit: ho provato django-command-extensionsDumpScript ma non funziona sul mio 2 GB di RAM PC con il mio gruppo di dati corrente.

risposta

9

Non ho mai dovuto farlo ma quello che proverei è.

  1. smettere di correre server
  2. pitone manage.py DumpData
  3. Alter settings.py per puntare al database Postgres appena creato
  4. pitone manage.py loadData
+1

pitone manage.py DumpData -> dalla memoria sul mio PC ... se provo app da app, è meglio, ma l'importazione non funziona . –

3

Per prima cosa mi basta provare un semplice:

sqlite3 sqllitedb .dump | psql postgresdb 

A quel punto, basta provarlo. Scrivi alcuni script di test in Django per produrre un set di record di esempio per ogni applicazione, quindi esegui un diff per assicurarti che siano identici. Se lo sono, allora la tua conversione probabilmente va bene.

Se questo non funziona ...

Mi consiglia di non utilizzare Django per scaricare e caricare i dati, dal momento che sto cercando di indovinare che non è ottimizzato per farlo.

Invece, vorrei creare una seconda versione della tua app con le corrette impostazioni del database PostgreSQL, eseguire syncdb per creare tutte le tabelle, quindi copiare i dati da mysqllite a PostgreSQL usando qualche altro strumento.

Il problema è che la maggior parte dei problemi durante la conversione dei dati si trova nelle definizioni della tabella, ecc. Quelli sembrano essere i più idiosincratici. Se è possibile generare uno script SQL che è un dump di solo il contenuto della tabella, è consigliabile utilizzare i comandi SQL standard INSERT INTO.

Onestamente, non riesco a capire perché ci sarebbero problemi con le chiavi esterne. Supponendo che sqlite stia creando chiavi estranee accurate (e perché no?) Allora non c'è modo che non copi correttamente. In realtà, le chiavi esterne non sono forme speciali di dati. Non è più probabile che il campo UserProfile.user_id conterrà un valore errato rispetto al campo UserProfile.photo. Se la preoccupazione di una chiave esterna è che i campi stessi non sono identificati correttamente come campi di chiavi esterne (cioè senza vincoli), allora l'opzione di creare prima il database utilizzando syncdb risolverà il problema.

Come per troncamento: a quanto ho capito, PostgreSQL genera un errore grave se i dati stanno per essere troncati. Non so se questo è il caso di sqlite o se solo tronca in silenzio. In ogni caso, assumendo nuovamente che sqlite non stia in qualche modo modificando i dati durante l'esportazione, i campi dovrebbero contenere dati di lunghezza appropriata per il campo in cui si trovano.L'unica cosa che posso pensare a questo potrebbe riguardare la codifica dei caratteri, quindi assicurati che i campi di PostgreSQL abbiano la stessa codifica delle tabelle sqlite, almeno durante l'importazione.

3

Un altro modo per farlo potrebbe essere l'utilizzo di più database.

http://docs.djangoproject.com/en/dev/topics/db/multi-db/

E 'importante leggere questa sezione.

http://docs.djangoproject.com/en/dev/topics/db/multi-db/#moving-an-object-from-one-database-to-another

Da quello che ho capito che significa che hanno fornito non ci sono dati nel nuovo DB, da dispositivi per esempio si potrebbe fare

queryset = MyModel.objects.using("old-db").all() 
for obj in queryset: 
    obj.save(using="new-db") 

causa che dovrebbe conservare le chiavi primarie I don' Penso che ci sarebbero stati problemi con le chiavi straniere.

23

In base alla mia esperienza, il ripristino di & da SQL non funziona correttamente.

Si dovrebbe seguire questa sequenza invece:

1. contenuti Dump db a JSON

$ ./manage.py dumpdata > dump.json 

2. Accendere il backend in settings.py

DATABASES = { 
    # COMMENT OUT: 
    # 'default': dj_database_url.config(default='sqlite:////full/path/to/your/database/file.sqlite'), 
    # ADD THIS INSTEAD: 
    'default': dj_database_url.config(default='postgres://localhost:5432/postgres_db_name'), 
} 

3. Syncdb e migrare il nuovo DB nella stessa struttura di tabella

$ ./manage.py syncdb 
$ ./manage.py migrate 

4. Caricare il json al nuovo db.

$ ./manage.py loaddata dump.json 

5. Complimenti! Ora i nuovi dati sono nel tuo postgres db.

+1

Attenzione, questo è inteso solo per le dimensioni del database più piccole http://stackoverflow.com/questions/23047766. loaddata carica l'intero json nella RAM sembra – pufferfish

+7

Ciò causa un errore: django.db.utils.IntegrityError: Problema durante l'installazione di fixture 'dump.json': Impossibile caricare contenttypes.ContentType (pk = 3): valore chiave duplicato viola un vincolo univoco "django_content_type_app_label_76bd3d3b_uniq" DETTAGLIO: Chiave (app_label, modello) = (auth, gruppo) esiste già. – matandked

+2

Per quanto riguarda il mio errore nell'ultimo commento, sembra * necessario * applicare "TRUNCATE django_content_type CASCADE;" * prima * usando loaddata. @Nimo potresti aggiornare la tua risposta? – matandked

6

Quello che segue è un perfezionamento della Nimo's answer e Stephen's answer per Django 1.7+:

  1. ./manage.py dumpdata --natural-primary --natural-foreign > dump.json
  2. Variazione DATABASES in settings.py per puntare al nuovo (PostgreSQL) db.
  3. ./manage.py migrate
  4. ./manage.py loaddata dump.json

Un problema che ho incontrato è che SQLite non sembra rispettare in realtà la lunghezza massima per CharField s. Nel mio caso, questo ha fatto fallire il passaggio loaddata. Sono stato in grado di trovare (ed eliminare) le istanze modello con troppo lunghi CharField valori tramite:

MyModel.objects.extra(where=["LENGTH(text) > 20"]).delete() 

Una volta che ho fatto questo prima del punto 1. sopra, tutto ha funzionato.

+0

Un problema qui è la migrazione dei dati di scrittura (es. Tipi di contenuto predefiniti). Eseguo la migrazione, quindi eseguo il flush, quindi troncano gli indici a zero, * quindi * loaddata. È molto da ricordare - e dimentico sempre qualcosa - ma funziona bene. – Oli

1

In @Nimo risposta, utilizzato da "syncdb",
"syncdb" non lavorato in django 1.9 (funziona su django 1,7), invece di che, utilizzando come segue:

python manage.py migrate.

E Postgres impostazione di configurazione è qui:

DATABASES = { 
    'default': { 
     'ENGINE': 'django.db.backends.postgresql_psycopg2', 
     'NAME': 'myproject', 
     'USER': 'myprojectuser', 
     'PASSWORD': 'password', 
     'HOST': 'localhost', 
     'PORT': '', 
    } 
} 
Problemi correlati