Pengumpulan koneksi dengan mssql-python

Pengumpulan koneksi meningkatkan performa aplikasi dengan menggunakan kembali koneksi database alih-alih membuat yang baru untuk setiap permintaan. Membuka koneksi melibatkan beberapa langkah yang memakan waktu:

  • Driver membuat soket jaringan.
  • Driver menyelesaikan jabat tangan TLS.
  • Driver melakukan autentikasi ke server.
  • Driver memvalidasi parameter koneksi.

Pengumpulan koneksi membuat koneksi tetap terbuka dan tersedia untuk digunakan kembali, sehingga aplikasi Anda tidak perlu mengulangi langkah-langkah ini untuk setiap permintaan.

Perilaku bawaan

Pengumpulan koneksi diaktifkan secara default saat Anda membuat koneksi pertama. Pengaturan default adalah:

Setting Nilai standar Deskripsi
max_size 100 Jumlah maksimum koneksi untuk setiap string koneksi yang unik.
idle_timeout 600 detik (10 menit) Jumlah detik sebelum koneksi siaga ditutup.
import mssql_python

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

Mengonfigurasi pengumpulan koneksi

Konfigurasikan pengumpulan sebelum membuat koneksi apa pun:

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

Fungsi pooling() menerima parameter berikut:

Parameter Jenis Default Deskripsi
max_size int 100 Jumlah maksimum koneksi gabungan per string koneksi.
idle_timeout int 600 Beberapa detik sebelum koneksi menganggur dikeluarkan dari kolam.
enabled bool Benar Aktifkan atau nonaktifkan pengumpulan.

Nonaktifkan pengumpulan koneksi

Untuk menonaktifkan pengumpulan, hubungi pooling() dengan enabled=False sebelum membuat koneksi:

import mssql_python

mssql_python.pooling(enabled=False)

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

Note

Atur konfigurasi pengumpulan sebelum membuat koneksi apa pun. Memanggil pooling() setelah membuat koneksi tidak berpengaruh.

Cara kerja pooling

Isolasi string koneksi

Setiap string koneksi yang unik memiliki pool independen masing-masing. Kumpulan tidak berbagi koneksi di berbagai string koneksi:

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

Siklus hidup koneksi

Dapatkan (mendapatkan koneksi):

  1. Kumpulan menghapus koneksi kedaluwarsa (kedaluwarsa).
  2. Kumpulan mencoba menggunakan kembali koneksi yang ada:
    • Ini memeriksa apakah koneksi hidup.
    • Ini mengatur ulang status koneksi.
    • Jika kedua pemeriksaan berhasil, itu mengembalikan koneksi.
  3. Jika tidak ada koneksi yang dapat digunakan kembali dan kumpulan berada di bawah max_size, driver membuat koneksi baru.
  4. Jika pool sudah mencapai kapasitas maksimum dan tidak ada koneksi yang valid, driver akan menghasilkan error.

Rilis (mengembalikan koneksi):

  1. Jika kolam memiliki kapasitas, kolam menyimpan koneksi untuk digunakan kembali.
  2. Jika pool berada pada max_size, driver akan segera menutup koneksi.

Pemeriksaan kesehatan koneksi

Driver melakukan pemeriksaan kesehatan koneksi sebelum menggunakan kembali koneksi yang dikumpulkan.

  1. Pemeriksaan langsung: Memastikan koneksi jaringan masih valid.
  2. Pemeriksaan reset: Mengatur ulang status sesi (tingkat isolasi, pengaturan) agar dapat digunakan kembali dengan bersih.

Jika salah satu pemeriksaan gagal, pool akan membuang koneksi tersebut dan membuat koneksi baru.

Pembersihan otomatis

  • Batas waktu siaga: Driver menutup koneksi yang tidak digunakan lebih lama dari idle_timeout nilainya.
  • Keluar proses: Handler atexit menutup semua koneksi yang dikumpulkan saat proses Python keluar.

Praktik terbaik

Ukuran kolam renang Anda dengan tepat

Cocokkan ukuran kumpulan Anda dengan konkurensi aplikasi Anda.

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

Menggunakan pengelola konteks

Pengelola konteks memastikan Anda mengembalikan koneksi ke kumpulan dengan benar.

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

Jaga agar string koneksi tetap konsisten

Parameter yang berbeda dalam string koneksi membuat kumpulan terpisah.

# 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

Pertimbangkan batas koneksi Azure SQL

Azure SQL Database memberlakukan batas koneksi berdasarkan tingkat layanan. Nilai berikut adalah perkiraan; periksa dokumentasi yang ditautkan untuk batas terbaru:

Tingkat layanan Jumlah koneksi bersamaan maksimum
Basic 30
Standar S0-S2 60-120
S3 standar dan versi yang lebih baru 200
Premium 500

Sesuaikan nilai max_size Anda agar berada di bawah batas berikut.

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

Sesuaikan waktu tunggu idle untuk beban kerja Anda

  • Koneksi yang sering: Gunakan nilai yang lebih panjang idle_timeout untuk menjaga koneksi tetap hangat.
  • Koneksi sporadis: Gunakan nilai yang lebih pendek idle_timeout untuk merilis sumber daya.
# 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

Keterbatasan

Implementasi saat ini memiliki beberapa keterbatasan dibandingkan dengan driver lain:

Feature Status
ClearPool() / ClearAllPools() Tidak tersedia.
Statistik/pemantauan kolam renang Tidak tersedia.
Penggantian kumpulan per koneksi Tidak tersedia.
Ukuran kolam renang minimum Tidak dapat dikonfigurasi.

Contoh: Pola aplikasi web

Contoh Flask berikut menunjukkan bagaimana koneksi dikumpulkan secara transparan di seluruh permintaan:

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

Mengenali kelelahan kolam renang

Saat semua koneksi di kumpulan sedang digunakan dan Anda meminta koneksi baru, Anda melihat gejala seperti:

  • Koneksi terhenti atau mengalami habis waktu saat menunggu koneksi yang tersedia.
  • Throughput aplikasi tiba-tiba turun saat menerima beban tinggi.
  • Penggunaan memori meningkat saat driver membuat koneksi yang tidak dapat digunakan kembali.

Penyebab umum:

  • Koneksi tidak dikembalikan ke kumpulan. Selalu tutup koneksi setelah selesai, atau gunakan pengelola konteks. Koneksi yang tidak ditutup tetap diperiksa.
  • Ukuran kolam terlalu kecil untuk beban kerja. Jika Anda memiliki 50 permintaan simultan tetapi max_size=20, 30 permintaan akan menunggu.
  • Kueri yang berjalan lama menahan koneksi. Bagi operasi yang panjang menjadi beberapa bagian atau gunakan koneksi khusus untuk pemrosesan batch.

Cara memperbaiki:

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