2010-08-13 18 views
13

Ich muss ein komplexes Projekt von SQLite nach PostgreSQL migrieren. scheint Viele Menschen Problem mit Fremdschlüssel zu haben, Daten truncature und so weiter ...Django: Was sind die besten Praktiken, um ein Projekt von SQLite zu PosgreSQL zu migrieren

  • Gibt es eine voll automatisierte Utility?
  • Muss ich einige Daten oder ein Schema vor der Migration überprüfen?

bearbeiten: Ich habe versucht, django-command-extensionsDumpScript aber es auf meinem 2GB RAM PC mit meinem aktuellen Datensatz nicht ausgeführt wird.

Antwort

9

Ich musste es nie tun, aber was ich versuchen würde ist.

  1. Stopp laufenden Server
  2. Python manage.py DumpData
  3. Alter settings.py in die neu geschaffene Postgres-Datenbank
  4. Python manage.py loaddata
+1

Python manage.py DumpData -> auf meinem PC nicht genügend Arbeitsspeicher ... Wenn ich App von App versuchen, es ist besser, aber der Import funktioniert nicht . –

3

Das Wichtigste zuerst Punkt I Probier einfach ein einfaches:

sqlite3 sqllitedb .dump | psql postgresdb 

At diesen Punkt, teste es einfach aus. Schreiben Sie einige Testskripts in Django, um eine Reihe von Beispieldatensätzen für jede Anwendung auszugeben, und führen Sie dann einen Vergleich durch, um sicherzustellen, dass sie identisch sind. Wenn dies der Fall ist, ist Ihre Konvertierung wahrscheinlich in Ordnung.

Wenn das nicht funktioniert ...

ich gegen die Verwendung von Django würde empfehlen, die Daten zu entleeren und zu laden, da ich so vermute ich wird es nicht tun optimiert.

Stattdessen würde ich eine zweite Version Ihrer App mit den korrekten PostgreSQL-Datenbankeinstellungen erstellen, syncdb ausführen, um alle Tabellen zu erstellen, und dann die Daten mit einem anderen Tool von mysqllite nach PostgreSQL kopieren.

Die Sache ist, die meisten Probleme bei der Konvertierung über Daten in den Tabellendefinitionen usw. Diese scheinen am eigenwilligsten zu sein. Wenn Sie ein SQL-Skript erstellen können, das nur ein Dump nur des Tabelleninhalts ist, sollte das ziemlich Standard SQL INSERT INTO Befehle sein.

Ehrlich gesagt kann ich nicht sehen, warum es ausländische Schlüsselprobleme geben würde. Angenommen, dass sqlite genaue Fremdschlüssel erstellt (und warum nicht?), Dann gibt es keine Möglichkeit, die nicht korrekt kopiert wird. Fremdschlüssel sind keine speziellen Daten. Es ist nicht wahrscheinlicher, dass das Feld UserProfile.user_id einen falschen Wert enthält als das Feld UserProfile.photo. Wenn das Fremdschlüsselproblem darin besteht, dass die Felder selbst nicht korrekt als Fremdschlüsselfelder identifiziert werden (d. H. Keine Einschränkungen), wird die Option, zuerst die Datenbank unter Verwendung von syncdb zu erstellen, dieses Problem beheben.

Per Trunkierung: Wie ich es verstehe, wirft PostgreSQL einen harten Fehler, wenn Daten kurz vor dem Absturz sind. Ich weiß nicht, ob dies bei sqlite der Fall ist oder ob es einfach stillschweigend abgeschnitten wird. In beiden Fällen, wiederum unter der Annahme, dass SQLite nicht irgendwie die Daten beim Export zusammenfasst, sollten die Felder Daten enthalten, die die richtige Länge für das Feld haben, in das sie gehen.Das einzige, was mir dabei einfällt, ist die Zeichencodierung. Stellen Sie daher sicher, dass die PostgreSQL-Felder die gleiche Codierung haben wie die SQLite-Tabellen, zumindest während des Imports.

3

Eine andere Möglichkeit, dies zu tun, kann die Verwendung mehrerer Datenbanken sein.

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

Es ist wichtig, dass Sie diesen Abschnitt lesen.

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

Von dem, was ich verstehe, dass Mittel, die bereitgestellt es keine Daten in Ihrem neuen DB ist, von Vorrichtungen zum Beispiel Sie

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

tun konnte, denn das ist der Primärschlüssel erhalten sollte ich don‘ Ich denke, es gäbe irgendwelche Probleme mit ausländischen Schlüsseln.

23

Meiner Erfahrung nach funktioniert Dumping & Wiederherstellung von SQL nicht ordnungsgemäß.

Sie diese Sequenz stattdessen folgen sollte:

1. Dump db Inhalt in

$ ./manage.py dumpdata > dump.json 

2. Schalten Sie das Backend JSon 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 und migrieren Sie die neue DB in die gleiche Tabellenstruktur

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

4. Legen Sie die Json auf die neue db.

$ ./manage.py loaddata dump.json 

5. Congrats! Jetzt sind die neuen Daten in Ihrer postgres db.

+1

Vorsicht, dies ist nur für kleinere Datenbankgrößen gedacht http://stackoverflow.com/questions/23047766. loaddata lädt den gesamten JSON in den RAM – pufferfish

+7

Dies verursacht einen Fehler: django.db.utils.IntegrityError: Problem beim Installieren der Fixture 'dump.json': containetypes.ContentType konnte nicht geladen werden (pk = 3): doppelter Schlüsselwert verletzt eindeutige Constraint "django_content_type_app_label_76bd3d3b_uniq" DETAIL: Schlüssel (app_label, model) = (auth, group) existiert bereits. – matandked

+2

In Bezug auf meinen Fehler im letzten Kommentar scheint es, dass Sie * TRUNCATE django_content_type CASCADE anwenden müssen; * vor * mit Ladedaten. @Nimo kannst du deine Antwort aktualisieren? – matandked

6

Das Folgende ist eine Verfeinerung von Nimo's answer und Stephen's answer für Django 1.7+:

  1. ./manage.py dumpdata --natural-primary --natural-foreign > dump.json
  2. ändern DATABASES in settings.py auf die neue (PostgreSQL) db Punkt.
  3. ./manage.py migrate
  4. ./manage.py loaddata dump.json

Ein Problem, das ich gestoßen ist, dass SQLite scheint nicht wirklich auf die maximale Länge für CharField s zu erzwingen. In meinem Fall hat dies den Schritt loaddata zum Scheitern gebracht. Ich war in der Lage zu finden (und löscht) Modellinstanzen mit zu langen CharField Werten über:

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

Sobald ich dies vor dem Schritt tat 1. oben, alles hat funktioniert.

+0

Ein Problem hier ist Migration schreibt Daten (z. B. Standard Inhaltstypen). Ich migriere, spüle dann und trenne die Indizes dann wieder auf Null, * dann * loaddata. Es ist eine Menge zu erinnern - und ich vergesse immer etwas - aber es funktioniert gut. – Oli

1

In @Nimo Antwort von "syncdb" verwendet, wird
"syncdb" nicht in django 1,9 (auf django arbeitet 1.7) gearbeitet, statt dass mit wie folgt vor:

python manage.py migrate.

Und Postgres Konfigurationseinstellung ist hier:

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