Kapcsolat-újrafelhasználás az mssql-pythonban

A kapcsolati pooling javítja az alkalmazás teljesítményét azáltal, hogy adatbázis-kapcsolatokat újrahasznosítanak, ahelyett, hogy minden kéréshez újakat hoznának létre. A kapcsolat megnyitása több időigényes lépést igényel:

  • Az illesztőprogram hálózati aljmentet hoz létre.
  • A sofőr befejezi a TLS kézfogást.
  • Az illesztőprogram hitelesíti a szervert.
  • Az illesztőprogram érvényesíti a kapcsolati paramétereket.

A kapcsolat pooling nyitva tartja a kapcsolatokat és újrahasznosítható, így az alkalmazásodnak nem kell minden kérésnél ismételnie ezeket a lépéseket.

Alapértelmezett viselkedés

A kapcsolat-összevonás alapértelmezetten engedélyezett, amikor létrehozod az első kapcsolatot. Az alapértelmezett beállítások a következők:

Setting Alapértelmezett érték Leírás
max_size 100 Maximális kapcsolatok egyedi kapcsolati karakterlánc szerint.
idle_timeout 600 másodperc (10 perc) Az inaktív kapcsolatok lezárása előtti másodpercek száma.
import mssql_python

# Pooling is automatically enabled with defaults
conn = mssql_python.connect(connection_string)

Kapcsolat-összevonás konfigurálása

Konfiguráld a poolinget, mielőtt bármilyen kapcsolatot létrehoznál:

import mssql_python

# Configure custom pool settings
mssql_python.pooling(max_size=50, idle_timeout=300)

# Now create connections
conn = mssql_python.connect(connection_string)

Parameters

A pooling() függvény a következő paramétereket fogadja el:

Paraméter Típus Default Leírás
max_size int 100 Kapcsolati karakterlánconként az összevont kapcsolatok maximális száma.
idle_timeout int 600 Másodpercekkel azelőtt, hogy az üres kapcsolatokat kilakoltatják a medencéből.
enabled bool True Engedélyezd vagy tiltsd ki a poolingolást.

A kapcsolat-újrafelhasználás letiltása

A kapcsolat-összevonás letiltásához hívja meg a(z) pooling() elemet a(z) enabled=False paraméterrel a kapcsolatok létrehozása előtt:

import mssql_python

mssql_python.pooling(enabled=False)

# Connections are now created and destroyed per use
conn = mssql_python.connect(connection_string)

Megjegyzés:

Állítsd be a pooling konfigurációt, mielőtt bármilyen kapcsolatot létrehoznál. A pooling() hívás kapcsolatok létrehozása után nem hatásos.

Hogyan működik a pooling

Kapcsolati lánc izolálása

Minden egyedi kapcsolati karakterlánc saját független poolt tart fenn. A poolok nem osztoznak meg különböző kapcsolódási láncok között:

# These use separate pools
conn1 = mssql_python.connect("Server=<server1>;Database=<database1>;...")
conn2 = mssql_python.connect("Server=<server2>;Database=<database2>;...")

Identitásizoláció

A legtöbb tokenalapú hitelesítési módszernél a meghajtó elkülönítve kezeli a kapcsolatkészleteket a kapcsolatot megnyitó Microsoft Entra-identitás alapján, így egy adott rendszerbiztonsági névvel hitelesített kapcsolatot nem ad át olyan hívónak, amely egy másik rendszerbiztonsági nevet használ. A kivétel a következő táblázat első sora, ahol a kulcs önmagában a kapcsolati karakterlánc.

A pool kulcs a hitelesítési módszertől függ:

Authentication Medence kulcs
SQL hitelesítés, megbízható kapcsolatok, szolgáltatáselvek, Windows integrált hitelesítés, és ActiveDirectoryInteractive Windows használata Csak kapcsolási lánc
Felügyelt identitás Kapcsolati lánc, valamint az ügyfélazonosító vagy a rendszer által hozzárendelt identitás
Eszközkód hitelesítés és interaktív hitelesítés más platformokon, mint a Windows Kapcsolati lánc, valamint a bejelentkezett fiók
DefaultAzureCredential, egy egyedi token_provider, és nyers hozzáférési tokenek Kapcsolati sztring, valamint a token kivonata

Mivel a token hash része az utolsó csoport kulcsának, minden különálló token saját készletet kap. Egy hosszú életű jogosultság, amely gyorsítótározott tokent ad vissza, továbbra is egy poolt használ újra. Az illesztőprogram lustán nyeri vissza az üres identitáskészleteket, ahogy a későbbi pool műveletek futnak, nem pedig háttérszál révén.

A driver csak akkor szerez tokeneket, amikor új kapcsolatot kell nyitnia, így egy pool találat nem szerez tokent.

Az illesztőprogram frissíti a kapcsolatpoolban lévő azon kapcsolatokat, amelyek tokenje a lejárat előtt 5 percen belül van, mielőtt a kapcsolatot átadná, így a hosszú életű kapcsolatpoolok nem adnak vissza olyan kapcsolatokat, amelyek hamarosan meghibásodnának.

Kapcsolati életciklus

Lekérés (kapcsolat létrehozása):

  1. A medence eltávolítja az elavult (alapjárati lejárt) csatlakozásokat.
  2. A pool megpróbálja újrahasznosítani egy meglévő kapcsolatot:
    • Ellenőrzi, hogy a kapcsolat él-e.
    • Visszaállítja a kapcsolati állapotot.
    • Ha mindkét ellenőrzés sikeres, visszaadja a kapcsolatot.
  3. Ha nincs újrahasználható kapcsolat, és a pool alatt max_sizevan, az illesztőprogram új kapcsolatot hoz létre.
  4. Ha a pool tele van és nincs érvényes kapcsolat, a meghajtó hibát okoz.

Felszabadítás (a kapcsolat visszaadása):

  1. Ha a medencében van kapacitás, akkor a kapcsolatot újrahasznosítja el.
  2. Ha a kapcsolatkészlet eléri a max_size értéket, az illesztőprogram azonnal lezárja a kapcsolatot.

Kapcsolati egészségellenőrzések

Az illesztőprogram ellenőrzi a kapcsolat állapotát, mielőtt újra felhasználná a kapcsolatkészletből származó kapcsolatot.

  1. Élő ellenőrzés: Biztosítja, hogy a hálózati kapcsolat továbbra is érvényes.
  2. Reset ellenőrzés: Visszaállítja a session állapotot (izolációs szint, beállítások) a tiszta újrahasználathoz.

Ha bármelyik próba sikertelen, a pool eldobja a kapcsolatot, és új kapcsolatot hoz létre.

Automatikus takarítás

  • Tétlenségi időkorlát: Az illesztőprogram lezárja azokat a kapcsolatokat, amelyeket a idle_timeout értéknél hosszabb ideig nem használnak.
  • Folyamatkilépés: Egy atexit kezelő lezárja az összes felosztott kapcsolatot, amikor a Python folyamat kilép.

Bevált gyakorlatok

Méretezd megfelelően a medencédet

Igazítsa a készlet méretét az alkalmazás egyidejűségi igényeihez.

# For a web application with 20 concurrent requests
mssql_python.pooling(max_size=25)  # Slightly more than expected concurrency

Használj kontextuskezelőket

A kontextuskezelők biztosítják, hogy a kapcsolatok megfelelően visszakerüljenek a kapcsolatpoolba.

with mssql_python.connect(connection_string) as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT TOP 5 Name, ListPrice FROM Production.Product")
    rows = cursor.fetchall()
# Connection returned to pool

Tartsd a kapcsolati láncokat konzisztens

A kapcsolódási láncok különböző paraméterei külön poolokat hoznak létre.

# These create THREE separate pools (inefficient)
conn1 = mssql_python.connect("Server=<server>;Database=<database>;Encrypt=yes;")
conn2 = mssql_python.connect("SERVER=<server>;DATABASE=<database>;ENCRYPT=yes;")  # Different case
conn3 = mssql_python.connect("Server=<server>;Database=<database>;Encrypt=yes;", timeout=30)  # Extra parameter

# Use a constant connection string instead
CONNECTION_STRING = "Server=<server>;Database=<database>;Encrypt=yes;"
conn1 = mssql_python.connect(CONNECTION_STRING)
conn2 = mssql_python.connect(CONNECTION_STRING)  # Same pool

Vegye figyelembe az Azure SQL kapcsolati korlátait

Azure SQL Database a szolgáltatási szint alapján érvényesíti a kapcsolati korlátokat. A következő értékek közelítőek; Nézd meg a linkelt dokumentációt a jelenlegi korlátokról:

Szolgáltatási szint Maximális egyidejű kapcsolatok száma
Alapszintű 30
Standard S0-S2 60-120
Standard S3 és későbbi verziók 200
prémium 500

Állítsd be az max_size értéket ezen korlátok alá.

# For Azure SQL Standard S2 (120 limit)
mssql_python.pooling(max_size=100)  # Leave headroom

Állítsa be az üresjárati időkorlátot a számítási feladathoz

  • Gyakori kapcsolatok: Hosszabb értéket használjunk, hogy melegen idle_timeout kapcsolatokat.
  • Szórványos kapcsolatok: Rövidebbidle_timeout értéket használj az erőforrások felszabadítására.
# High-frequency API: keep connections warm
mssql_python.pooling(idle_timeout=1800)  # 30 minutes

# Batch job running every hour: release between runs
mssql_python.pooling(idle_timeout=60)  # 1 minute

Limitations

A jelenlegi megvalósításnak vannak korlátai más meghajtókhoz képest:

Feature Status
ClearPool() / ClearAllPools() Nem érhető el
Készletstatisztikák/figyelés Nem érhető el
Kapcsolatonkénti pool felülbírálása Nem érhető el
Minimális medence méret Nem konfigurálható.

Példa: Webalkalmazási minta

A következő Flask-példa bemutatja, hogyan történik a kapcsolatok készletezése a kérések között a háttérben:

import mssql_python
from flask import Flask, g

app = Flask(__name__)

# Configure pooling at startup
mssql_python.pooling(max_size=20, idle_timeout=300)

def get_db():
    if 'db' not in g:
        g.db = mssql_python.connect(app.config['DATABASE_URL'])
    return g.db

@app.teardown_appcontext
def close_db(error):
    db = g.pop('db', None)
    if db is not None:
        db.close()  # Returns to pool

@app.route('/products')
def list_products():
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("SELECT TOP 5 Name, ListPrice FROM Production.Product")
    return cursor.fetchall()

Ismerd fel a medence kimerültséget

Amikor az összes csatlakozás a medencében használatban van, és új kapcsolatot kérsz, olyan tüneteket látsz, mint például:

  • A kapcsolatok megakadnak vagy időtúllépnek, miközben egy szabad kapcsolatra várnak.
  • Az alkalmazás áteresztőképessége hirtelen csökken terhelés alatt.
  • A memóriahasználat nő, ahogy az illezőprogram olyan kapcsolatokat hoz létre, amelyeket nem tud újrahasznosítani.

Gyakori okok:

  • A csatlakozásokat nem viszik vissza a medencébe. Mindig zárd le a kapcsolatokat, ha végeztél, vagy használj kontextuskezelőket. A le nem zárt kapcsolat lefoglalva marad.
  • A medence mérete túl kicsi a munkaterheléshez. Ha 50 egyidejű kérésed van, de max_size=20, akkor 30 kérés várakozik.
  • A hosszú ideig futó lekérdezések lefoglalják a kapcsolatokat. Bontsd szét a hosszú műveleteket, vagy használj dedikált kapcsolatokat kötött munkahoz.

A javítás módja:

# 1. Always use context managers to guarantee return
with mssql_python.connect(connection_string) as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT ...")
    rows = cursor.fetchall()
# Connection returned to pool here, even if an exception occurs

# 2. Size the pool to match your concurrency
mssql_python.pooling(max_size=50)  # Match or slightly exceed expected concurrent connections

# 3. Reduce idle timeout if connections go stale
mssql_python.pooling(idle_timeout=120)