SDK's en toepassingen integreren
Voor het integreren van Azure Database for PostgreSQL in uw toepassingen moet u de juiste clientbibliotheken kiezen, verbindingen effectief beheren en fouten probleemloos afhandelen. In deze les worden SDK-integratiepatronen voor Python beschreven, samen met aanbevolen procedures die van toepassing zijn op programmeertalen.
Opmerking
Codevoorbeelden in deze les laten patronen zien voor het integreren van PostgreSQL met uw toepassingen. De psycopg bibliotheek wordt regelmatig bijgewerkt. Ga naar de psycopg-documentatie voor de meest recente API-details en aanbevolen procedures.
Python-integratie met psycopg
De psycopg bibliotheek (versie 3) is de aanbevolen PostgreSQL-adapter voor Python. Het biedt zowel synchrone als asynchrone interfaces, groepsgewijze verbindingen en volledige ondersteuning voor PostgreSQL-functies.
Installeer psycopg met pip en gebruik de extra optie 'binary' voor de eenvoudigste installatie: pip install "psycopg[binary]". De binaire distributie bevat vooraf gecompileerde afhankelijkheden, waardoor u geen PostgreSQL-clientbibliotheken hoeft te installeren op uw ontwikkelcomputer. Voor productie-implementaties waarbij u moet compileren op basis van specifieke PostgreSQL-clientbibliotheken, installeert u zonder de binaire extra en zorgt u ervoor dat libpq ontwikkelheaders beschikbaar zijn.
Maak verbindingen met behulp van psycopg.connect() met een verbindingsreeks of met afzonderlijke parameters. Verbindingsreeksen zijn handig voor configuratiebestanden, terwijl afzonderlijke parameters flexibiliteit bieden voor het programmatisch berekenen van waarden, zoals het ophalen van wachtwoorden uit 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")
Contextbeheerders zorgen ervoor dat verbindingen correct worden gesloten, zelfs wanneer er uitzonderingen optreden. Het buitenste with blok beheert de verbinding en het binnenste with blok beheert de 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()
Gebruik altijd geparameteriseerde query's om SQL-injectieaanvallen te voorkomen. Geparameteriseerde query's scheiden de SQL-structuur van de gegevenswaarden, zodat het databasestuurprogramma de juiste escapebewerkingen kan afhandelen. Gebruik %s tijdelijke aanduidingen voor positionele parameters of %(name)s voor benoemde parameters. Gebruik nooit tekenreeksopmaak of samenvoeging om query's te bouwen met gebruikersinvoer.
Haal queryresultaten op met behulp van cursormethoden die overeenkomen met uw behoeften. Gebruik fetchone() wanneer u een enkele rij verwacht, fetchall() voor kleine resultaatssets en door de cursor direct te itereren voor grote resultaten, om te voorkomen dat alles tegelijk in het geheugen wordt geladen.
Best practices voor verbindingsbeheer
Effectief verbindingsbeheer verbetert de betrouwbaarheid en prestaties van toepassingen, ongeacht de programmeertaal die u gebruikt.
Stel de juiste time-outs in om te voorkomen dat uw toepassing vastloopt wanneer de database onbereikbaar is of query's langer worden uitgevoerd dan verwacht. Verbindingstime-outs bepalen hoe lang de client wacht om een verbinding tot stand te brengen, terwijl time-outs van instructie de uitvoeringstijd van query's beperken. Kies time-outwaarden op basis van de tolerantie van uw toepassing voor latentie. Webtoepassingen gebruiken doorgaans kortere time-outs (vijf tot 30 seconden) dan batchverwerkingstaken.
conn = psycopg.connect(
connection_string,
connect_timeout=10,
options="-c statement_timeout=30000" # milliseconds
)
Implementeer logica voor opnieuw proberen met exponentieel uitstel om tijdelijke fouten van netwerkproblemen, opnieuw opstarten van de server of resourceconflicten af te handelen. Catch OperationalError voor verbindings- en time-outfouten. Probeer het niet opnieuw bij schendingen van beperkingen of syntaxisfouten. Deze vereisen codewijzigingen, geen nieuwe pogingen.
Sluit altijd verbindingen wanneer u er klaar mee bent. Gelekte verbindingen maken de verbindingsgroep leeg en kunnen nieuwe verbindingen voorkomen. Contextbeheerders bieden automatische opschoning die ook werkt wanneer er uitzonderingen optreden.
Strategieën voor foutafhandeling
Databasebewerkingen kunnen om verschillende redenen mislukken. Het afhandelen van fouten verbetert de gebruikerservaring en vereenvoudigt foutopsporing.
Verbindingsfouten treden op wanneer de server onbereikbaar is of de verbinding weigert: netwerkproblemen, onjuiste referenties, firewallregels of serveronderhoud kunnen allemaal oorzaken hebben. Afhandelen van verbindingsfouten door logboekgegevens te registreren voor het oplossen van problemen tijdens het presenteren van gebruiksvriendelijke berichten aan eindgebruikers.
Unieke beperkingen, refererende sleutels en controlebeperkingen veroorzaken specifieke fouten wanneer deze worden geschonden. Catch UniqueViolation, ForeignKeyViolation, en CheckViolation om zinvolle feedback te geven. Rol de transactie altijd terug na een schending van een beperking.
Doodlopen treden op wanneer twee transacties wachten op elkaars vergrendelingen, wat een cirkelafhankelijkheid creëert. PostgreSQL detecteert automatisch impasses en beëindigt één transactie. Uw toepassing moet DeadlockDetected vangen, terugdraaien en opnieuw uitvoeren. Om impasserisico's te minimaliseren, ontwerpt u transacties om vergrendelingen in een consistente volgorde te verkrijgen. Behandel LockNotAvailable op dezelfde manier bij een time-out voor queries die wachten op vergrendelingen.
Prestatie-overwegingen
Patronen op toepassingsniveau kunnen de prestaties van de database aanzienlijk beïnvloeden.
Voeg meerdere rijen in één instructie in in plaats van afzonderlijke invoegingen in een lus uit te voeren. Batchbewerkingen verminderen netwerkrondes, waardoor de doorvoer voor bulkgegevensbewerkingen aanzienlijk wordt verbeterd. Gebruiken executemany voor het invoegen van honderden tot een paar duizend rijen. Voor grotere gegevenssets (meer dan 10.000 rijen) biedt de COPY opdracht de hoogste prestaties, vaak twee tot 10 keer sneller dan afzonderlijke invoegingen:
with cur.copy("COPY messages (conversation_id, role, content) FROM STDIN") as copy:
for record in records:
copy.write_row(record)
Voorbereide instructies kunnen de prestaties verbeteren voor query's die herhaaldelijk worden uitgevoerd met verschillende parameters. De database parseert de query eenmaal en plant deze vervolgens opnieuw. De meeste PostgreSQL-stuurprogramma's gebruiken automatisch voorbereide instructies voor geparameteriseerde query's.
Het maken van nieuwe databaseverbindingen is duur. Voor elk netwerk zijn handshakes, verificatie en resourcetoewijzing aan de serverzijde vereist. Gebruik verbindingsgroepen om herbruikbare verbindingen te onderhouden die uw toepassing kan lenen en retourneren:
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,))