mssql-python ile bağlantı havuzu

Bağlantı havuzu, her istek için yeni bağlantı oluşturmak yerine veritabanı bağlantılarını yeniden kullanarak uygulama performansını artırır. Bir bağlantı açmak, çok zaman alan adımları içerir:

  • Sürücü bir ağ soketi kurar.
  • Sürücü TLS el sıkışmasını tamamlar.
  • Sürücü, sunucu ile kimlik doğrulamasını sağlar.
  • Sürücü bağlantı parametrelerini doğrular.

Bağlantı havuzu bağlantıları açık ve yeniden kullanıma açık tutar, böylece uygulamanız her istek için bu adımları tekrarlamasına gerek kalmaz.

Varsayılan davranış

İlk bağlantınızı oluşturduğunuzda bağlantı havuzu varsayılan olarak etkinleştiriliyor . Varsayılan ayarlar şunlardır:

Setting Varsayılan değer Açıklama
max_size 100 Her benzersiz bağlantı dizesi için maksimum bağlantı sayısı.
idle_timeout 600 saniye (10 dakika) Boşta bağlantıların kapanmasından önceki saniye sayısı.
import mssql_python

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

Bağlantı havuzunu yapılandırma

Bağlantı oluşturmadan önce havuzlamayı yapılandırın:

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

pooling() işlevi aşağıdaki parametreleri kabul eder:

Parametre Türü Varsayılan Açıklama
max_size int 100 Bağlantı dizesi başına izin verilen en fazla havuz bağlantısı sayısı.
idle_timeout int 600 Boşta bağlantıların havuzdan tahliye edilmesinden saniyeler önce.
enabled bool True Havuzlamayı etkinleştirin veya devre dışı bırakın.

Bağlantı havuzunu devre dışı bırak

Havuzlamayı devre dışı bırakmak için, bağlantılar oluşturmadan önce pooling() öğesini enabled=False ile çağırın:

import mssql_python

mssql_python.pooling(enabled=False)

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

Note

Bağlantı kurmadan önce havuzlama konfigürasyonunu ayarlayın. Bağlantılar oluşturulduktan sonra pooling() çağrısının hiçbir etkisi yoktur.

Havuzlama nasıl çalışır?

Bağlantı dizisi izolasyonu

Her benzersiz bağlantı dizesi kendine ait bağımsız bir havuza sahiptir. Havuzlar, farklı bağlantı dizileri arasında bağlantıları paylaşmaz:

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

Bağlantı yaşam döngüsü

Edinin (bağlantı kurun):

  1. Havuz, eskimiş (boşta kalma süresi dolmuş) bağlantıları kaldırır.
  2. Havuz, mevcut bir bağlantıyı yeniden kullanmaya çalışır:
    • Bağlantının canlı olup olmadığını kontrol eder.
    • Bağlantı durumunu sıfırlıyor.
    • Her iki kontrol de başarılı olursa, bağlantı geri döner.
  3. Yeniden kullanılabilir bir bağlantı yoksa ve havuz max_size değerinin altındaysa, sürücü yeni bir bağlantı oluşturur.
  4. Havuz kapasitesi doluysa ve geçerli bağlantı yoksa, sürücü hata oluşturur.

Serbest bırakma (bir bağlantının geri verilmesi):

  1. Havuzun kapasitesi varsa, bağlantıyı yeniden kullanmak üzere saklar.
  2. Havuz max_size durumundaysa, sürücü bağlantıyı hemen kapatır.

Bağlantı durumu denetimleri

Sürücü, bağlantı havuzundaki bir bağlantıyı yeniden kullanmadan önce bağlantı durum denetimleri gerçekleştirir.

  1. Canlı kontrol: Ağ bağlantısının hâlâ geçerli olduğundan emin olur.
  2. Sıfırlama kontrolü: Temiz tekrar kullanım için oturum durumunu (izolasyon seviyesi, ayarlar) sıfırlar.

Eğer herhangi bir kontrol başarısız olursa, havuz bağlantıyı atar ve yeni bir bağlantı oluşturur.

Otomatik temizlik

  • Boşta zaman aşımı: Sürücü, değerden idle_timeout daha uzun süre kullanılmayan bağlantıları kapatır.
  • Sürecin sonlanması: Bir atexit işleyici, Python işlemi sonlandığında havuzdaki tüm bağlantıları kapatır.

En iyi uygulamalar

Havuzunuzu uygun şekilde ölçün

Havuz büyüklüğünü uygulamanızın eşzamanlılığıyla eşleştirin.

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

Bağlam yöneticileri kullanın

Bağlam yöneticileri, bağlantıları havuza doğru şekilde geri göndermenizi sağlar.

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

Bağlantı dizelerini tutarlı tutun

Bağlantı dizelerindeki farklı parametreler ayrı havuzlar oluşturur.

# 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

Azure SQL bağlantı sınırlarını göz önünde bulundurun

Azure SQL Veritabanı, hizmet seviyesine göre bağlantı sınırlarını uygular. Aşağıdaki değerler yaklaşık olarak belirlenmiştir; Mevcut sınırlar için bağlantılı dokümantasyonu kontrol edin:

Hizmet katmanı En fazla eşzamanlı bağlantı
Basic 30
Standart S0-S2 60-120
Standart S3 ve sonraki sürümler 200
Premium 500

max_size değerinizi bu sınırların altında ayarlayın.

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

İş yükünüze göre boşta zaman aşımını ayarlayın

  • Sık bağlantılar: Bağlantıları sıcak tutmak için daha uzun idle_timeout bir değer kullanın.
  • Sporadik bağlantılar: Kaynakları serbest bırakmak için daha idle_timeout kısa bir değer kullanın.
# 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

Mevcut uygulamanın diğer sürücülere kıyasla bazı sınırlamaları vardır:

Özellik Statü
ClearPool() / ClearAllPools() Mevcut değil.
Havuz istatistikleri/izleme Mevcut değil.
Bağlantı başına havuz geçersiz kılma Mevcut değil.
Minimum havuz büyüklüğü Yapılandırılamaz.

Örnek: Web uygulama deseni

Aşağıdaki Flask örneği, bağlantıların istekler arasında şeffaf şekilde nasıl toplandığını gösterir:

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

Havuz yorgunluğunu tanı

Havuzdaki tüm bağlantılar kullanılıyor ve yeni bağlantı talep ettiğinizde, aşağıdaki gibi belirtiler görürsünüz:

  • Bağlantılar ücretsiz bağlantı beklerken takılır ya da zaman bitiyor.
  • Uygulamanın işleme kapasitesi yük altında aniden düşer.
  • Sürücü tekrar kullanamayacağı bağlantılar oluşturdukça bellek kullanımı da artıyor.

Yaygın nedenler:

  • Bağlantılar havuza geri dönmez. İşiniz bitince her zaman bağlantıları kapatın ya da bağlam yöneticileri kullanın. Kapalı olmayan bir bağlantı kontrol altında kalır.
  • Havuz iş yükü için çok küçük. 50 eşzamanlı isteğiniz varsa ancak max_size=20 30 istek bekler.
  • Uzun süreli sorgular bağlantıları taşır. Uzun operasyonları ayırın veya toplu iş için özel bağlantılar kullanın.

Nasıl düzeltilir:

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