Poolování spojení s mssql-python

Poolování spojení zlepšuje výkon aplikací tím, že znovu používá databázová spojení místo vytváření nových pro každý požadavek. Otevření spojení zahrnuje několik časově náročných kroků:

  • Ovladač nastavuje síťovou zásuvku.
  • Ovladač dokončí navázání spojení TLS.
  • Ovladač se autentizuje na serveru.
  • Ovladač ověřuje parametry připojení.

Poolování spojení udržuje spojení otevřená a dostupná pro opětovné použití, takže vaše aplikace nemusí tyto kroky opakovat pro každý požadavek.

Výchozí chování

Poolování připojení je ve výchozím nastavení zapnuté při vytváření prvního připojení. Výchozí nastavení jsou:

Setting Výchozí hodnota Popis
max_size 100 Maximální počet spojení na jeden unikátní připojovací řetězec.
idle_timeout 600 sekund (10 minut) Počet sekund před uzavřením nečinných spojů.
import mssql_python

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

Konfigurace sdružování připojení

Před vytvořením jakýchkoli spojení nakonfigurujte pooling:

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

Funkce pooling() přijímá následující parametry:

Parameter Typ Výchozí Popis
max_size int 100 Maximální počet sdružených připojení pro každý připojovací řetězec.
idle_timeout int 600 Sekundy před tím, než jsou nečinné spoje vyřazeny z bazénu.
enabled bool Pravdivé Povolte nebo vypněte pooling.

Zakázat sdružování připojení

Chcete-li sdružování připojení zakázat, před vytvořením připojení zavolejte pooling() s enabled=False:

import mssql_python

mssql_python.pooling(enabled=False)

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

Note

Nastavte konfiguraci poolingu před navázáním jakýchkoli spojení. Volání pooling() po vytvoření spojení nemá žádný vliv.

Jak funguje pooling

Izolace spojovacích řetězců

Každý jedinečný připojovací řetězec udržuje svůj vlastní nezávislý pool. Pooly nesdílejí spojení přes různé řetězce spojů:

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

Životní cyklus spojení

Získání (navázání spojení):

  1. Pool odstraňuje zastaralé (nečinné a expirované) spojení.
  2. Pool se pokouší znovu použít existující připojení:
    • Kontroluje, jestli je spojení živé.
    • Resetuje stav připojení.
    • Pokud obě kontroly uspějí, obnoví spojení.
  3. Pokud neexistuje znovupoužitelné připojení a pool je pod max_size, ovladač vytvoří nové připojení.
  4. Pokud je pool na kapacitě bez platných spojení, ovladač zobrazí chybu.

Uvolnění (vrácení spojení):

  1. Pokud má bazén kapacitu, uloží spojení pro opětovné použití.
  2. Pokud je pool na , max_sizeovladač okamžitě ukončí spojení.

Kontroly stavu spojení

Ovladač provádí kontrolu stavu připojení před opětovným použitím sdíleného připojení.

  1. Kontrola dostupnosti: Ověřuje, zda je síťové připojení stále aktivní.
  2. Kontrola resetu: Resetuje stav relace (úroveň izolace, nastavení) pro bezproblémové opětovné použití.

Pokud některá kontrola selže, pool spojení zahodí a vytvoří nový.

Automatické čištění

  • Časový limit nečinnosti: Ovladač uzavírá spoje, která nejsou používána déle než je jejich hodnota idle_timeout .
  • Ukončení procesu: Handler uzavírá všechna spojená atexit spojení, když Python proces ukončí.

Osvědčené postupy

Velikost bazénu je vhodná

Přizpůsobte velikost poolu souběžnosti vaší aplikace.

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

Používejte správce kontextu

Správci kontextu zajišťují, že správně vracíte spojení do poolu.

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

Udržujte spojovací řetězce konzistentní

Různé parametry v řetězcích spojení vytvářejí samostatné pooly.

# 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

Zvažte omezení připojení Azure SQL

Azure SQL Database vynucuje limity připojení podle úrovně služby. Následující hodnoty jsou přibližné; Zkontrolujte související dokumentaci pro aktuální limity:

Úroveň služby Maximální počet souběžných připojení
Basic 30
Standardní S0-S2 60-120
Standardní verze S3 a pozdější 200
Premium 500

Nastavte hodnotu max_size pod tyto limity.

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

Upravte časový limit nečinnosti pro vaši úlohu

  • Časté připojení: Používejte delší idle_timeout hodnotu, abyste udrželi spojení teplé.
  • Občasná připojení: Použijte kratší hodnotu idle_timeout, aby se uvolnily prostředky.
# 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

Současná implementace má oproti ostatním ovladačům určitá omezení:

funkce Stav
ClearPool() / ClearAllPools() Není k dispozici.
Statistiky/monitorování fondu Není k dispozici.
Přepsání fondu pro každé připojení Není k dispozici.
Minimální velikost bazénu Nekonfigurovatelné.

Příklad: vzor webové aplikace

Následující příklad Flask ukazuje, jak jsou spojení transparentně sdílena napříč požadavky:

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

Rozpoznat vyčerpání bazénu

Když jsou všechna připojení v poolu obsazena a požádáte o nové připojení, vidíte příznaky jako:

  • Připojení se zasekne nebo vyprší, zatímco čekáme na volné připojení.
  • Propustnost aplikací náhle klesne pod zátěží.
  • Spotřeba paměti stoupá, protože ovladač vytváří spojení, která nemůže znovu použít.

Běžné příčiny:

  • Připojení se do poolu nevrací. Vždy po dokončení uzavírejte kontakty, nebo používejte správce kontextu. Spojení, které není uzavřené, zůstává kontrolované.
  • Bazén je příliš malý na pracovní zátěž. Pokud máte 50 současných požadavků, ale max_size=20, 30 požadavků čeká.
  • Dlouhodobé dotazy udržují spojení. Rozdělte dlouhé operace nebo používejte vyhrazená připojení pro dávkovou práci.

Postup opravy:

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