Migration von Postgresql zu Sqlite

SQLite und PostgreSQL sind beides beliebte Datenbanksysteme, die in Django-Projekten eingesetzt werden können, obwohl sie für verschiedene Anwendungsfälle gedacht sind.

SQLite ist eine serverlose, selbständige SQL-Datenbank, die hauptsächlich für kleinere Projekte, Prototyping und für Anwendungen, die nur von einer einzelnen Person oder einem kleinen Team verwendet werden, geeignet ist. Es ist die Standarddatenbank für Django-Projekte und kommt mit Python, was die Einrichtung sehr einfach macht. SQLite speichert Daten in einer einzigen Datei und benötigt keine separate Datenbanksoftware oder -dienste, was es perfekt für Entwicklungsumgebungen oder kleine Anwendungen macht. Allerdings kann es bei gleichzeitigem Zugriff von vielen Benutzern zu Leistungseinbussen kommen und es fehlen einige erweiterte Datenbankfunktionen, die in anderen Datenbanksystemen verfügbar sind.

PostgreSQL hingegen ist ein leistungsstarkes, open-source, objektrelationales Datenbanksystem. Es ist gut für den Produktiveinsatz geeignet und kann grosse Mengen an Daten und viele gleichzeitige Benutzer handhaben. PostgreSQL bietet eine Vielzahl von erweiterten Funktionen wie komplexe Abfragen, Transaktionskontrolle, Multi-Version Concurrency Control (MVCC), und es unterstützt auch JSON-Felder, was es sehr flexibel und leistungsfähig für komplexere Anwendungen macht. Django hat eine ausgezeichnete Unterstützung für PostgreSQL und viele Django-spezifische Funktionen wie ArrayFields, HStore und JSONFields erfordern PostgreSQL. Die Einrichtung von PostgreSQL kann allerdings etwas komplizierter sein als SQLite, insbesondere in Bezug auf die Installation und Konfiguration des Servers.

Entwicklungsworkflow in Django

Unser Entwicklungsworkflow sieht grundsätzlich wie folgt aus:

  1. Lokale Entwicklungsumgebung, mit SQLite als Datenbank. Hier kann gebaut und gepropt werden und je nachdem können sogar ganze Datenbanken in GIT gespeichert werden, so dass auch andere Entwickler mit dem gleichen Datenbestand entwickeln können.
  2. Testumgebung hat eine PostgreSQL Server. Wir wollen sicher sein, dass es auch wirklich funktioniert, da sich die Funktionen und Datentypen in bestimmten Fällen nicht gleich verhalten.
  3. Produktivumgebung. Hier entstehen die Daten und hier wird gearbeitet.

Produktive Daten in Entwicklungsumgebung übernehmen

Es gibt immer wieder kuriose Situationen, wo die Software nicht das macht, was sie sollte. In den meisten Fällen klar ersichtlich, in einigen Fällen nicht so klar ersichtlich mit einem grösseren Debugging Aufwand. Debuggen in einer Produktivumgebung ist nicht sonderlich schön.

Mit den folgenden Schritten gelingt die Datenmigration von PostgreSQL zu SQLite:

  1. Mit PgAdmin ein Backup der produktiven machen. Dabei die folgenden Optionen verwenden:
    • Format: Plain
    • Options: “Use Column Inserts”
  2. Mittels dem folgenden Python Script das entstandene SQL Script säubern:
import re

input_file = 'data.sql'
output_file = 'fixed-data.sql'

# Definiere die regulären Ausdrücke, nach denen gesucht und gelöscht werden sollen
regex_expressions = [
    r'SET [a-z_ =0-9\']*;',
    r'SELECT pg_catalog.set_config.*;',
    r'CREATE SCHEMA public;',
    r'ALTER SCHEMA public OWNER TO postgres;',
    r'COMMENT ON SCHEMA public IS \'standard public schema\';',
    r'public\.',
    r'CREATE INDEX[ a-z_0-9()]*;',
    r'SET client_encoding = \'UTF8\';',
    r'ALTER TABLE [a-z_]* OWNER TO postgres;',
    r'ALTER TABLE[\n\r \w()\.,]*;',
    r'CREATE INDEX[ \w()]*;',
    r"SELECT[ \w\.',()]*\);",
    r'--[\w ():;\.-]*' #remove comments
]

# Lade den Inhalt der Eingabedatei
with open(input_file, 'r') as input_f:
    input_content = input_f.read()

# Durchsuche den Inhalt nach den regulären Ausdrücken und entferne sie
for pattern in regex_expressions:
    input_content = re.sub(pattern, '', input_content, flags=re.MULTILINE)

# Schreibe den bereinigten Inhalt in die Ausgabedatei
with open(output_file, 'w') as output_f:
    output_f.write(input_content)

# Benachrichtigung, dass der Vorgang abgeschlossen ist
print('Durchsuchen und Löschen der Zeilen abgeschlossen.')

Und jetzt das Script wie folgt starten:

python mysql.py

Damit werden alle Ausdrücke, welche von SQLite nicht verstanden werden entfernt. Jetzt kann die Datei bequem über ein Tool oder die Kommandozeile eingelesen:

"C:\Program Files (x86)\sqlite-tools\sqlite3.exe" travelmanager.db < fixed-data.sql