Správa spojení pomocí mssql-python

Většina aplikací následuje jednoduchý vzor: otevřít spojení, spustit dotazy, ukončit spojení. Následující sekce se věnují otevírání a zavírání spojení, používání správců kontextu, konfiguraci automatického commitu a práci s atributy spojení.

Otevřete spojení

Použijte connect() tuto funkci k navázání spojení. Předejte připojovací řetězec obsahující údaje o serveru, databázi a ověřovací údaje:

import mssql_python

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

Funkce connect() přijímá:

  • Připojovací řetězec jako první poziční argument nebo klíčové slovo connection_str.
  • Jednotlivá klíčová slova, která ovladač sloučí do připojovacího řetězce.
  • Další možnosti jako autocommit, timeout, a attrs_before.

Můžete kombinovat oba přístupy. Klíčová slova přepíší hodnoty v připojovacím řetězci, což je užitečné, když v konfiguraci ukládáte základní připojovací řetězec a při každém volání přepisujete nastavení, například timeout:

# 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
)

Uzavřít spojení

Vždy po dokončení uzavírejte připojení, abyste je vrátili do poolu a uvolnili serverové zdroje. Neuzavřená připojení zabírají paměť na straně serveru a mohou nakonec vyčerpat fond připojení, což může způsobit, že nové pokusy o připojení budou blokovány nebo selžou.

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

Jakmile je spojení uzavřeno, nelze ho použít:

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

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

Volání close() opakovaně je bezpečné (idempotentní):

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

Kontextoví manažeři

Použijte with příkaz ke správě spojení ve většině aplikací. Zaručuje, že ovladač uzavře připojení při opuštění bloku, i když dojde k výjimce. Tento přístup eliminuje riziko úniku spojení z zapomenutých close() hovorů:

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

Správce kontextu ukončí spojení při ukončení provozu. Automaticky nepotvrzuje ani nevrací transakce:

  • Vždy: Při ukončení volá close(), bez ohledu na to, zda došlo k výjimce.
  • close() chování: Pokud autocommit=False, všechny nezávazné změny jsou při uzavření spojení vráceny zpět.
  • Musíte volat conn.commit() výslovně, abyste změny zachovali.

Tento návrh odpovídá chování podle PEP 249 a zabraňuje nechtěným částečným potvrzením transakcí. Pokud váš kód vyvolá výjimku před dosažením commit(), probíhající transakce je bezpečně vrácena zpět:

# 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

Režim automatického dokončování

Ve výchozím nastavení platí, že autocommit=False, což znamená, že každý příkaz běží v rámci implicitní transakce. Musíte zavolat conn.commit(), abyste uložili změny, nebo zavolat conn.rollback(), abyste je zahodili. Implicitní transakce jsou nejbezpečnější volbou pro úpravy dat, protože umožňují seskupit více příkazů do jedné atomové operace.

Povolte automatické potvrzování, pokud chcete, aby se každý příkaz ihned potvrdil. Automatické potvrzování je užitečné pro operace DDL (CREATE TABLE, ALTER INDEX), úlohy pouze pro čtení nebo administrativní skripty, kde není potřeba transakce seskupovat:

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

Povolte automatické potvrzení, aby se každý příkaz okamžitě potvrdil. Použijte autocommit=True při připojení nebo jej po připojení přepněte pomocí setautocommit() nebo přímým přiřazením vlastnosti:

# 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

Časový limit připojení vypršel

Nastavte časový limit připojení tak, aby se kontrolovalo, jak dlouho ovladač čeká na navázání spojení, než vyvolá chybu. Rozumný časový limit připojení je důležitý pro aplikace nasazené v prostředích s nespolehlivými sítěmi nebo pro rychlé selhání, když je server nedostupný:

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

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

Časový limit 0 znamená bez časového limitu (čeká se neomezeně dlouho). Definujte rozumné časové limity ve výrobě; pokus o zaseknutí spojení bez časového limitu trvale zablokuje volací vlákno.

Atributy připojení

Použijte set_attr() k úpravě chování spojení za běhu. Atributy připojení řídí nízkoúrovňová nastavení ovladačů, jako je režim přístupu, izolace transakcí a velikost paketu. Většina aplikací tyto atributy nemusí měnit, ale jsou užitečné pro konkrétní situace:

  • Režim pouze pro čtení: Zabraňuje náhodným zápisům v reportovacích dotazech.
  • Izolace transakcí: Určuje, jak se souběžné transakce vzájemně ovlivňují (pro zajištění přísné konzistence použijte SERIALIZABLE, pro běžné použití READ_COMMITTED).
  • Velikost paketu: Ladit pro sítě s vysokou latencí nebo vysokou propustností.
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)

Dostupné atributy:

Konstanta Popis
SQL_ATTR_CONNECTION_TIMEOUT Časový limit připojení v sekundách.
SQL_ATTR_LOGIN_TIMEOUT Časový limit přihlášení v sekundách.
SQL_ATTR_PACKET_SIZE Velikost síťového paketu.
SQL_ATTR_ACCESS_MODE Režim pouze pro čtení nebo čtení a zápis.
SQL_ATTR_TXN_ISOLATION Úroveň izolace transakcí.
SQL_ATTR_CURRENT_CATALOG Aktuální název databáze.

Atributy předběžného připojení

Některé atributy musí být nastaveny předtím, než ovladač naváže připojení (například časový limit přihlášení). Pošlete je dál attrs_before:

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

Získání informací o připojení

Použití getinfo() pro získávání metadat ovladačů a serverů pro logování, diagnostiku nebo přizpůsobení chování na základě schopností serveru:

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)}")

Získejte seznam dostupných informačních konstant:

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

Vyhledávat escape znak

Vlastnost searchescape vrací znak používaný k escapování zástupných znaků (% a _) ve vzorech LIKE. Použijte ho k bezpečnému vyhledávání doslovných žolíkových znaků v uživatelském vstupu:

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

Kódování a dekódování

Nastavte kódování textu pro SQL příkazy a výsledky. Výchozí nastavení funguje pro většinu aplikací. Měňte je pouze pokud se připojíte na server, který používá ne-UTF-8 kódování char/varchar pro sloupce. Kódování, které server používá, závisí na kolaci sloupců:

# 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)

Výchozí kódování:

Direction Typ SQL Výchozí kódování
Odchozí (str) SQL_WCHAR utf-16le
Příchozí SQL_CHAR utf-8
Příchozí SQL_WCHAR utf-16le
Příchozí SQL_WMETADATA utf-16le

Osvědčené postupy

  • Používejte správce kontextu (with bloky) pro všechna spojení v aplikačním kódu. Zaručují úklid i v případě výjimek.
  • Používejte sdružování připojení pro lepší výkon (ve výchozím nastavení povoleno). Viz Sdružování spojení.
  • Nastavte vhodné časové limity pro vaše síťové prostředí. 30sekundový časový limit je vhodný pro většinu cloudových nasazení; zvyšte jej pro připojení mezi regiony nebo přes VPN.
  • Použití autocommit=False (výchozí) pro scénáře úpravy dat, kde potřebujete transakční atomicitu.
  • Použití autocommit=True pro DDL operace, dotazy pouze pro čtení a administrátorské skripty.
  • Nesdílejte spojení mezi vlákny. Úroveň bezpečnosti vláken ovladače je 1 (vlákna mohou sdílet modul, ale nikoli připojení).