Integrieren von SDKs und Anwendungen

Abgeschlossen

Die Integration von Azure Database for PostgreSQL in Ihre Anwendungen erfordert die Auswahl geeigneter Clientbibliotheken, das effektive Verwalten von Verbindungen und die ordnungsgemäße Behandlung von Fehlern. Diese Lektion behandelt SDK-Integrationsmuster für Python sowie bewährte Methoden, die für Programmiersprachen gelten.

Hinweis

Codebeispiele in dieser Lektion veranschaulichen Muster für die Integration von PostgreSQL in Ihre Anwendungen. Die psycopg Bibliothek wird häufig aktualisiert. Besuchen Sie die Psycopg-Dokumentation für die aktuellsten API-Details und bewährten Methoden.

Python-Integration mit psycopg

Die psycopg Bibliothek (Version 3) ist der empfohlene PostgreSQL-Adapter für Python. Es bietet sowohl synchrone als auch asynchrone Schnittstellen, Verbindungspooling und vollständige Unterstützung für PostgreSQL-Features.

Installieren Sie psycopg mit pip und dem Binary-Extra für die einfachste Einrichtung: pip install "psycopg[binary]". Die binäre Verteilung enthält vorkompilierte Abhängigkeiten, wodurch die Installation von PostgreSQL-Clientbibliotheken auf Ihrem Entwicklungscomputer vermieden wird. Installieren Sie für Produktionsbereitstellungen, bei denen Sie gegen bestimmte PostgreSQL-Clientbibliotheken kompilieren müssen, ohne das binäre Extra, und stellen Sie sicher, dass libpq Entwicklungsheader verfügbar sind.

Erstellen Sie Verbindungen mithilfe von psycopg.connect() mit entweder einer Verbindungszeichenfolge oder einzelnen Parametern. Verbindungszeichenfolgen sind praktisch für Konfigurationsdateien, während einzelne Parameter flexibilität für die programmgesteuerte Berechnung von Werten bieten, z. B. das Abrufen von Kennwörtern aus Key Vault:

import psycopg

# Connection string format
conn = psycopg.connect("postgresql://user:password@myserver.postgres.database.azure.com/mydb?sslmode=require")

# Individual parameters
conn = psycopg.connect(host="myserver.postgres.database.azure.com", dbname="mydb",
                       user="myuser", password="mypassword", sslmode="require")

Kontextmanager stellen sicher, dass Verbindungen ordnungsgemäß geschlossen werden, auch wenn Ausnahmen auftreten. Der äußere with Block verwaltet die Verbindung, und der innere with Block verwaltet den Cursor:

with psycopg.connect(connection_string) as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT * FROM conversations WHERE id = %s", (conversation_id,))
        row = cur.fetchone()

Verwenden Sie parametrisierte Abfragen immer, um SQL-Einfügungsangriffe zu verhindern. Parametrisierte Abfragen trennen die SQL-Struktur von den Datenwerten, sodass der Datenbanktreiber die richtige Escapeung verarbeiten kann. Verwenden Sie %s Platzhalter für Positionsparameter oder %(name)s für benannte Parameter. Verwenden Sie niemals die Zeichenfolgenformatierung oder Verkettung, um Abfragen mit Benutzereingaben zu erstellen.

Rufen Sie Abfrageergebnisse mithilfe von Cursormethoden ab, die Ihren Anforderungen entsprechen. Verwenden Sie fetchone(), wenn Sie eine einzelne Zeile erwarten, fetchall() für kleine Resultsets und durchlaufen Sie den Cursor direkt für große Ergebnisse, um zu vermeiden, dass alles gleichzeitig in den Arbeitsspeicher geladen wird.

Bewährte Methoden für die Verbindungsverwaltung

Effektive Verbindungsverwaltung verbessert die Zuverlässigkeit und Leistung der Anwendung unabhängig von der verwendeten Programmiersprache.

Legen Sie geeignete Timeouts fest, um zu verhindern, dass die Anwendung hängen bleibt, wenn die Datenbank nicht erreichbar ist oder Abfragen länger als erwartet ausgeführt werden. Verbindungstimeouts steuern, wie lange der Client wartet, um eine Verbindung herzustellen, während Anweisungszeitüberschreitungen die Ausführungszeit der Abfrage begrenzen. Wählen Sie Timeoutwerte basierend auf der Toleranz Ihrer Anwendung für Latenz aus– Webanwendungen verwenden in der Regel kürzere Timeouts (fünf bis 30 Sekunden) als Batchverarbeitungsaufträge.

conn = psycopg.connect(
    connection_string,
    connect_timeout=10,
    options="-c statement_timeout=30000"  # milliseconds
)

Implementieren Sie Wiederholungslogik mit exponentiellem Backoff, um vorübergehende Fehler von Netzwerkproblemen, Serverneustarts oder Ressourcenkonflikten zu behandeln. Fangen Sie OperationalError bei Verbindungs- und Timeoutfehlern ab. Wiederholen Sie keinen Wiederholungsversuch bei Einschränkungen oder Syntaxfehlern – für diese sind Codeänderungen erforderlich, keine Wiederholungen.

Schließen Sie immer Verbindungen, wenn Sie damit fertig sind. Durchleckte Verbindungen erschöpfen den Verbindungspool und können neue Verbindungen verhindern. Kontextmanager bieten eine automatische Bereinigung, die auch dann funktioniert, wenn Ausnahmen auftreten.

Strategien zur Fehlerbehandlung

Datenbankvorgänge können aus verschiedenen Gründen fehlschlagen. Die Behandlung von Fehlern verbessert die Benutzerfreundlichkeit entsprechend und vereinfacht das Debuggen.

Verbindungsfehler treten auf, wenn der Server nicht erreichbar ist oder die Verbindung ablehnt– Netzwerkprobleme, falsche Anmeldeinformationen, Firewallregeln oder Serverwartung können alle Ursachen haben. Behandeln Sie Verbindungsfehler, indem Sie Details zur Problembehandlung bei der Darstellung von benutzerfreundlichen Nachrichten an Endbenutzer protokollieren.

Eindeutige Einschränkungen, Fremdschlüssel und Überprüfungseinschränkungen lösen bei Verstößen bestimmte Fehler aus. Fangen Sie UniqueViolation, ForeignKeyViolation und CheckViolation, um aussagekräftiges Feedback zu geben. Führen Sie nach einer Einschränkungsverletzung immer einen Rollback für die Transaktion durch.

Deadlocks treten auf, wenn zwei Transaktionen aufeinander warten, wodurch eine zyklische Abhängigkeit entsteht. PostgreSQL erkennt Deadlocks automatisch und beendet eine Transaktion. Ihre Anwendung sollte DeadlockDetected abfangen, ein Rollback durchführen und einen neuen Versuch starten. Um das Deadlock-Risiko zu minimieren, entwerfen Sie Transaktionen, um Sperren in einer konsistenten Reihenfolge zu erwerben. Behandeln Sie LockNotAvailable das Gleiche, wenn Abfragen timeout auf Sperren warten.

Leistungsüberlegungen

Muster auf Anwendungsebene können sich erheblich auf die Datenbankleistung auswirken.

Fügen Sie mehrere Zeilen in eine einzelne Anweisung ein, anstatt einzelne Einfügungen in einer Schleife auszuführen. Batchvorgänge reduzieren Netzwerk-Roundtrips und verbessern den Durchsatz für Massendatenvorgänge erheblich. Verwenden Sie executemany, um Hunderte bis zu ein paar tausend Zeilen einzufügen. Bei größeren Datasets (10.000 Zeilen+ Zeilen) bietet der COPY Befehl die höchste Leistung, häufig zwei bis 10 Mal schneller als einzelne Einfügungen:

with cur.copy("COPY messages (conversation_id, role, content) FROM STDIN") as copy:
    for record in records:
        copy.write_row(record)

Vorbereitete Anweisungen können die Leistung für Abfragen verbessern, die wiederholt mit unterschiedlichen Parametern ausgeführt werden. Die Datenbank analysiert und plant die Abfrage einmal, und verwendet dann diesen Plan wieder. Die meisten PostgreSQL-Treiber verwenden automatisch vorbereitete Anweisungen für parametrisierte Abfragen.

Das Erstellen neuer Datenbankverbindungen ist teuer – jede erfordert Netzwerk-Handshakes, Authentifizierung und serverseitige Ressourcenzuordnung. Verwenden Sie Verbindungspools, um wiederverwendbare Verbindungen aufrechtzuerhalten, die Ihre Anwendung ausleihen und zurückgeben kann:

from psycopg_pool import ConnectionPool

pool = ConnectionPool(connection_string, min_size=1, max_size=10)

with pool.connection() as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT * FROM messages WHERE conversation_id = %s", (id,))

Weitere Ressourcen