Verwalte Verbindungen mit mssql-python

Die meisten Anwendungen folgen einem einfachen Muster: eine Verbindung öffnen, Abfragen ausführen, die Verbindung schließen. Die folgenden Abschnitte behandeln das Öffnen und Schließen von Verbindungen, die Verwendung von Kontextmanagern, die Konfiguration von Autocommit und die Arbeit mit Verbindungsattributen.

Eröffne eine Verbindung

Nutze die connect() Funktion, um eine Verbindung herzustellen. Übergebe eine Verbindungszeichenfolge mit deinem Server, deiner Datenbank und Authentifizierungsdaten:

import mssql_python

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;Database=<database>;"
    "Authentication=ActiveDirectoryDefault;Encrypt=yes"
)

Die Funktion connect() akzeptiert:

  • Eine Verbindungszeichenfolge als erstes positionales Argument oder das Schlüsselwort connection_str.
  • Einzelne Schlüsselwörter, die der Treiber in den Verbindungszeichenfolge einfügt.
  • Andere Optionen wie autocommit, timeout, und attrs_before.

Du kannst beide Ansätze kombinieren. Schlüsselwörter überschreiben Werte in der Verbindungszeichenfolge, was nützlich ist, wenn Sie eine Basisverbindungszeichenfolge in der Konfiguration speichern und Einstellungen wie timeout bei jedem Aufruf überschreiben:

# Base connection string from config, with per-call overrides
conn = mssql_python.connect(
    "Server=<server>.database.windows.net;Database=<database>;"
    "Authentication=ActiveDirectoryDefault;Encrypt=yes",
    timeout=30,
    autocommit=True
)

Schließe eine Verbindung

Schließen Sie immer die Verbindungen, wenn Sie fertig sind, um sie in den Connection Pool zurückzugeben und Serverressourcen freizugeben. Nicht geschlossene Verbindungen binden serverseitigen Speicher und können den Verbindungspool schließlich ausschöpfen, sodass neue Verbindungsversuche blockiert werden oder fehlschlagen.

conn = mssql_python.connect(connection_string)
try:
    # Use the connection
    cursor = conn.cursor()
    cursor.execute("SELECT 1")
finally:
    conn.close()

Einmal geschlossen, kann die Verbindung nicht mehr verwendet werden:

conn.close()
print(conn.closed)  # True

# This raises an error
cursor = conn.cursor()  # InterfaceError: Cannot create cursor on closed connection

Mehrmaliges Aufrufen von close() ist sicher (idempotent):

conn.close()
conn.close()  # No error

Kontextmanager

Verwenden Sie die Anweisung, with um Verbindungen in den meisten Anwendungen zu verwalten. Es garantiert, dass der Treiber die Verbindung beim Verlassen des Blocks schließt, selbst wenn eine Ausnahme auftritt. Dieser Ansatz eliminiert das Risiko geleakter Verbindungen durch vergessene close() Anrufe:

with mssql_python.connect(connection_string) as conn:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
    cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
    conn.commit()  # Must commit explicitly when autocommit=False
# Connection automatically closed

Der Kontextmanager schließt die Verbindung beim Verlassen. Es schreibt Transaktionen nicht automatisch fest und setzt sie auch nicht zurück:

  • Immer: Ruft close() beim Beenden auf, unabhängig davon, ob eine Ausnahme aufgetreten ist oder nicht.
  • close() Verhalten: Wenn autocommit=False, werden alle nicht verpflichteten Änderungen zurückgesetzt, wenn die Verbindung geschlossen wird.
  • Sie müssen conn.commit()explizit aufrufen, um Änderungen zu speichern.

Dieses Design folgt dem Verhalten von PEP 249 und verhindert versehentliche teilweise Commits. Wenn Ihr Code vor Erreichen commit()eine Ausnahme erzeugt, wird die laufende Transaktion sicher zurückgesetzt:

# Equivalent manual code:
conn = mssql_python.connect(connection_string)
try:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
    cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
    conn.commit()  # Must commit explicitly
finally:
    conn.close()  # Rolls back uncommitted changes if autocommit=False

Autocommit-Modus

Standardmäßig gilt autocommit=False, was bedeutet, dass jede Aussage innerhalb einer impliziten Transaktion ausgeführt wird. Du musst conn.commit() aufrufen, um Änderungen zu speichern, oder conn.rollback(), um sie zu verwerfen. Implizite Transaktionen sind die sicherste Wahl für Datenmodifikationen, da sie es ermöglichen, mehrere Anweisungen zu einer einzigen atomaren Operation zusammenzufassen.

Aktivieren Sie Autocommit, wenn Sie möchten, dass jede Aussage sofort committen soll. Autocommit ist nützlich für DDL-Operationen (CREATE TABLE, ALTER INDEX), schreibgeschützte Workloads oder administrative Skripte, bei denen keine Transaktionsgruppierung erforderlich ist:

conn = mssql_python.connect(connection_string)
print(conn.autocommit)  # False

cursor = conn.cursor()
cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
conn.commit()  # Required to persist changes

Aktiviere Autocommit für jede Statement, um sofort zu committen. Verwenden Sie autocommit=True beim Verbindungsaufbau, oder schalten Sie es nach dem Herstellen der Verbindung mit setautocommit() oder durch direkte Eigenschaftszuweisung um:

# At connection time
conn = mssql_python.connect(connection_string, autocommit=True)

# Or after connection (both forms work)
conn.setautocommit(True)
conn.autocommit = True
print(conn.autocommit)  # True

# Now changes are committed automatically
cursor = conn.cursor()
cursor.execute("SELECT TOP 1 Name FROM Production.Product")
print(cursor.fetchone().Name)
# No commit() needed

Verbindungstimeout

Stellen Sie das Verbindungs-Timeout ein, um zu steuern, wie lange der Treiber wartet, um eine Verbindung herzustellen, bevor er einen Fehler auslöst. Ein angemessener Verbindungszeitpunkt ist wichtig für Anwendungen, die in Umgebungen mit unzuverlässigen Netzwerken bereitgestellt werden oder für schnelle Fehlfunktionen, wenn ein Server nicht erreichbar ist:

# At connection time (in seconds)
conn = mssql_python.connect(connection_string, timeout=30)

# Or after connection
conn.timeout = 60
print(conn.timeout)  # 60

Eine Zeitüberschreitung von 0 bedeutet, dass keine Zeitüberschreitung erfolgt (es wird unbegrenzt gewartet). Definieren Sie angemessene Timeouts in der Produktion; Ein hängender Verbindungsversuch ohne Timeout blockiert den aufrufenden Thread dauerhaft.

Verbindungsattribute

Verwenden Sie set_attr(), um das Verbindungsverhalten zur Laufzeit zu ändern. Verbindungsattribute steuern Low-Level-Treibereinstellungen wie Zugriffsmodus, Transaktionsisolation und Paketgröße. Die meisten Anwendungen müssen diese Attribute nicht ändern, sind aber für bestimmte Szenarien nützlich:

  • Nur-Lese-Modus: Verhindert versehentliche Schreibvorgänge bei Berichtsanfragen.
  • Transaktionsisolation: Steuert, wie gleichzeitige Transaktionen interagieren (verwenden Sie SERIALIZABLE für strikte Konsistenz, READ_COMMITTED für den allgemeinen Gebrauch).
  • Paketgröße: Optimieren Sie auf Netzwerke mit hoher Latenz oder hohem Durchsatz.
import mssql_python

conn = mssql_python.connect(connection_string)

# Set read-only mode
conn.set_attr(mssql_python.SQL_ATTR_ACCESS_MODE, mssql_python.SQL_MODE_READ_ONLY)

# Set transaction isolation level
conn.set_attr(mssql_python.SQL_ATTR_TXN_ISOLATION, mssql_python.SQL_TXN_SERIALIZABLE)

Verfügbare Attribute:

Dauerhaft Beschreibung
SQL_ATTR_CONNECTION_TIMEOUT Verbindungs-Timeout in Sekunden.
SQL_ATTR_LOGIN_TIMEOUT Anmeldezeit in Sekunden.
SQL_ATTR_PACKET_SIZE Netzwerkpaketgröße.
SQL_ATTR_ACCESS_MODE Schreib-nur-Modus oder Lese-Schreib-Modus.
SQL_ATTR_TXN_ISOLATION Transaktionsisolationsniveau.
SQL_ATTR_CURRENT_CATALOG Aktueller Name der Datenbank.

Präkonnektivitätsattribute

Einige Attribute müssen festgelegt werden, bevor der Treiber die Verbindung herstellt (zum Beispiel das Anmelde-Timeout). Leiten Sie sie durch attrs_before:

conn = mssql_python.connect(
    connection_string,
    attrs_before={
        mssql_python.SQL_ATTR_LOGIN_TIMEOUT: 30,
        mssql_python.SQL_ATTR_CONNECTION_TIMEOUT: 60,
    }
)

Abrufen von Verbindungsinformationen

Verwendung getinfo() zum Abrufen von Treiber- und Servermetadaten für Protokollierung, Diagnostik oder Anpassung des Verhaltens basierend auf Serverfähigkeiten:

conn = mssql_python.connect(connection_string)

# Server information
print(f"Server name: {conn.getinfo(mssql_python.SQL_SERVER_NAME)}")
print(f"Database name: {conn.getinfo(mssql_python.SQL_DATABASE_NAME)}")

# Driver information
print(f"Driver name: {conn.getinfo(mssql_python.SQL_DRIVER_NAME)}")
print(f"Driver version: {conn.getinfo(mssql_python.SQL_DRIVER_VER)}")

Erhalten Sie eine Liste der verfügbaren Informationskonstanten:

constants = mssql_python.get_info_constants()
for name, value in constants.items():
    print(f"{name}: {value}")

Suche-Escape-Zeichen

Die Eigenschaft searchescape gibt das Zeichen zurück, das als Escape-Zeichen für Platzhalterzeichen (% und _) in LIKE-Mustern verwendet wird. Nutzen Sie es, um sicher nach wörtlichen Wildcard-Zeichen in Benutzereingaben zu suchen:

escape = conn.searchescape

# Use in queries with wildcard characters
cursor.execute(
    f"SELECT Name FROM Production.Product WHERE Name LIKE '%{escape}%%' ESCAPE '{escape}'"
)
# Matches names containing literal '%' character

Codierung und Decodierung

Konfigurieren Sie Textkodierung für SQL-Anweisungen und Ergebnisse. Die Standardeinstellungen funktionieren für die meisten Anwendungen. Ändere sie nur, wenn du dich mit einem Server verbindest, der eine nicht-UTF-8-Kodierung für char/varchar Spalten verwendet. Die Kodierung, die ein Server verwendet, hängt von der Spalten-Kollation ab:

# Set encoding for outbound text
conn.setencoding(encoding='utf-8')

# Get current encoding settings
settings = conn.getencoding()
print(settings)  # {'encoding': 'utf-8', 'ctype': ...}

# Set decoding for inbound text from specific SQL types
conn.setdecoding(mssql_python.SQL_CHAR, encoding='utf-8')

# Get current decoding settings
settings = conn.getdecoding(mssql_python.SQL_CHAR)
print(settings)

Standardkodierungen:

Richtung SQL-Typ Standardkodierung
Ausgehend (str) SQL_WCHAR utf-16le
Eingehend SQL_CHAR utf-8
Eingehend SQL_WCHAR utf-16le
Eingehend SQL_WMETADATA utf-16le

Bewährte Methoden

  • Verwenden Sie Kontextmanager (with Blöcke) für alle Verbindungen im Anwendungscode. Sie garantieren eine Reinigung, selbst wenn Ausnahmen auftreten.
  • Nutze Connection Pooling für bessere Leistung (standardmäßig aktiviert). Siehe Verbindungspooling.
  • Setze passende Timeouts für deine Netzwerkumgebung. Ein 30-Sekunden-Timeout eignet sich für die meisten Cloud-Deployments; Erhöhe sie für regionsübergreifende oder VPN-Verbindungen.
  • Verwenden Sie autocommit=False (die Standardoption) für Szenarien mit Datenänderungen, in denen Sie transaktionale Atomizität benötigen.
  • Verwenden Sie autocommit=True für DDL-Operationen, schreibgeschützte Abfragen und Admin-Skripte.
  • Teile keine Verbindungen über Threads hinweg. Die Thread-Sicherheitsstufe des Treibers beträgt 1 (Threads können das Modul gemeinsam nutzen, aber keine Verbindungen).