mssql-python sorunlarını giderme

SQL Server, Azure SQL Veritabanı, Azure SQL Yönetilen Örneği ve Microsoft Fabric’deki SQL veritabanına bağlanmak için mssql-python sürücüsünü kullanırken karşılaşılan yaygın sorunları tanılayın ve giderin.

Kurulum sorunları

pip kurulumu başarısız olur veya kaynaktan derlenir

Belirti -leri:

error: Microsoft Visual C++ 14.0 or greater is required
ERROR: Failed building wheel for mssql-python

Olası nedenler ve çözümler:

  • Platformunuz için önceden yapılmış bir tekerlek yok

    • Desteklenen bir Python sürümü (3.10 ve daha sonraki sürümler) ve platform kullandığınıza dikkat edin. Uyumluluk matrisi için Destek Yaşam Döngüsü bölümüne bakın. pip install --upgrade pip ile kurulum yapmadan önce pip'i yükseltin. Tekrarlanabilir ekip ortamları için, Tekrarlanabilir dağıtımlarda kilitli iş akışını veya Container ve yerel geliştirmedeki konteyner desenlerini kullanarak yerel makine kaymasını azaltabilirsiniz.
  • Sanal ortam etkinleştirilmedi

    • Önce sanal ortamınızı etkinleştirin. Sisteme Python yüklemek izin hatalarına veya çatışmalara yol açabilir.
    python -m venv .venv
    .venv\Scripts\activate
    pip install mssql-python
    

  • Eksik Linux sistem kütüphaneleri

Çelişkili sürücü kurulumları

Belirti -leri:

Aynı ortamda pyodbc ile birlikte mssql-python yüklendikten sonra içe aktarma hataları veya beklenmeyen davranışlar.

Düzeltme:

mssql-python ve pyodbc bir arada var olabilir. Çatışmalar görürseniz, temiz bir sanal ortam oluşturun:

python -m venv .venv --clear
.venv\Scripts\activate
pip install mssql-python

Bağlantı sorunları

Sunucuya bağlanamıyor

Belirti -leri:

OperationalError: [08001] (0) Client unable to establish connection

Olası nedenler ve çözümler:

  • Sunucuya ulaşılamaz

    • Sunucu adı ve portun doğru olduğundan emin olun.
    • Ağ bağlantısını kontrol et: ping servername veya telnet servername 1433.
    • Güvenlik duvarının 1433 portunda giden bağlantılara izin verdiğinden emin olun.
  • SQL Server çalışmıyor

    • SQL Server servisinin başlatıldığından emin olun.
    • İsimli örnekler için, SQL Server Browser hizmetinin çalıştığını doğrulayın.
  • Azure SQL firewall rules

    • İstemci IP'nizi Azure portalındaki Azure SQL güvenlik duvarı kurallarına ekleyin.
    • Azure SQL Yönetilen Örneği için, izin verilen bir ağdan bağlandığınızdan emin olun.
# Test basic connectivity
import socket
try:
    sock = socket.create_connection(("<server>.database.windows.net", 1433), timeout=5)
    print("TCP connection successful")
    sock.close()
except Exception as e:
    print(f"Cannot reach server: {e}")

Oturum açılamadı

Belirti -leri:

OperationalError: [28000] (18456) Login failed for user 'username'.

Olası nedenler ve çözümler:

  • Kimlik doğrulama modu uyumsuzluğu

    • Azure SQL Veritabanı, Azure SQL Yönetilen Örneği ve Fabric'teki SQL veritabanı için Authentication=ActiveDirectoryDefault gibi bir Microsoft Entra modunu tercih edin.
    • SQL doğrulamasını kasıtlı olarak kullanıyorsanız, sunucunun izin verdiğini ve o uç nokta için doğru giriş formatını kullandığınızı kontrol edin.
  • Yanlış SQL kimlik doğrulama bilgileri

    • Kullanıcı adı ve şifreyi doğrulayın.
    • Azure SQL için, tam kullanıcı adınızı ekleyin: username@servername.
  • Kullanıcı veritabanında yok

    • Kullanıcının belirtilen veritabanına erişimi olduğunu doğrulayın.
    • Giriş işleminin bir veritabanı kullanıcısına eşlenip eşlemediğini kontrol edin.
  • Kimlik doğrulama yapılandırılmadı

    • Microsoft Entra kimlik doğrulamasını kullanın (önerilir): Authentication=ActiveDirectoryDefault.
    • Eğer SQL kimlik doğrulamasını kabul etmesi gereken yerel bir SQL Server'ı sorun gideriyorsanız, SQL Server'ın karışık mod kimlik doğrulaması kullandığını doğrulayın.

Bağlantı zaman aşımına uğradı

Belirti -leri:

OperationalError: [HYT00] (0) Timeout expired
OperationalError: [HYT01] (0) Connection timeout expired

Olası nedenler ve çözümler:

  • Sunucu yavaş yanıt veriyor

    • Bağlantı süresini artırın:
    conn = mssql_python.connect(connection_string, timeout=60)
    
  • Ağ gecikme süresi

    • Sunucuya ağ yolunu kontrol et.
    • Daha kısa bir ağ yolu veya VPN kullanmayı düşünün.
  • Sunucu ağır yük altında

    • Yoğun olmayan saatlerde bağlantı kurmayı deneyin.
    • Veritabanı yöneticinizle iletişime geçin.

SSL sertifikası hataları

Belirti -leri:

OperationalError: [08001] SSL Provider: The certificate chain was issued by an authority that is not trusted

Çözümler:

İlk olarak, güvenilir bir sertifikayı veya Container ile yerel geliştirmedeki yerel geliştirme kalıplarını tercih edin. Sadece kontrol ettiğiniz bir sunucuya karşı yerel geliştirme için kullanın TrustServerCertificate=yes .

Kendi imzalı sertifika ile geliştirme ve test için:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDefault;"
    "Encrypt=yes;"
    "TrustServerCertificate=yes;"  # Don't use in production
)

Caution

TrustServerCertificate=yes sadece yerel bir yedek yöntemdir. Bunu paylaşılan devcontainer'lara, CI boru hatlarına veya üretim dağıtımlarına taşımayın. Daha geniş rehberlik için bkz. Şifreleme ve sertifikalar.

Üretim için, uygun sertifikaların kurulduğundan ve şu şekilde kullanıldığından emin olun:

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

Sorgu yürütme sorunları

Tablo veya nesne bulunamadı

Belirti -leri:

ProgrammingError: [42S02] (208) Invalid object name 'TableName'.

Olası nedenler ve çözümler:

  • Yanlış veritabanı bağlamı

    # Ensure you're connected to the correct database
    cursor.execute("SELECT DB_NAME()")
    print(cursor.fetchone()[0])
    
  • Belirtilmemiş şema

    # Use fully qualified name
    cursor.execute("SELECT * FROM dbo.TableName")
    
  • Tablo yok

    # Check if table exists
    cursor.execute("""
         SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES 
         WHERE TABLE_NAME = 'TableName'
    """)
    

Söz dizimi hatası

Belirti -leri:

ProgrammingError: [42000] (102) Incorrect syntax near '...'.

Çözümler:

  1. Önce SSMS'de SQL'i test ederek sözdizimi doğrulamak

  2. Dize kaçışını kontrol edin - parametreli sorgular kullanın:

    # Wrong - vulnerable to syntax issues and SQL injection
    cursor.execute(f"SELECT * FROM Production.Product WHERE Name = '{name}'")
    
    # Correct - use parameters
    cursor.execute("SELECT * FROM Production.Product WHERE Name = %(name)s", {"name": name})
    

Parametre hataları

Belirti -leri:

ProgrammingError: [07001] Wrong number of parameters

Çözümler:

  1. Yer tutucuları ve parametreleri sayın - eşleşmeleri gerekiyor

  2. Doğru parametre stilini seçin:

    # Qmark style - positional
    cursor.execute("SELECT * FROM Production.Product WHERE ProductID = ? AND Name LIKE ?", (1, "Adjustable%"))
    print(cursor.fetchone())
    
    # Pyformat style - named
    cursor.execute("SELECT * FROM Production.Product WHERE ProductID = %(id)s AND Name LIKE %(name)s", {"id": 1, "name": "Adjustable%"})
    print(cursor.fetchone())
    

Veri tipi sorunları

Tarih saati dönüşüm hataları

Belirti -leri:

DataError: [22007] Invalid datetime format

Çözümler:

Dizeler yerine Python datetime nesnelerini kullanın:

from datetime import datetime

cursor.execute("CREATE TABLE #Events (EventDate DATETIME)")

# Wrong - this raises an error for invalid dates
try:
    cursor.execute("INSERT INTO #Events (EventDate) VALUES (%(event_date)s)", {"event_date": "2024-13-45"})
except Exception as e:
    print(f"Expected error: {e}")

# Correct - use Python datetime objects
cursor.execute("INSERT INTO #Events (EventDate) VALUES (%(event_date)s)", {"event_date": datetime(2024, 3, 15)})
cursor.execute("SELECT EventDate FROM #Events")
print(cursor.fetchone())

Ondalık hassasiyet sorunları

Belirti -leri:

Sayılar kısaltılmış veya yanlış yuvarlanmış gibi görünür.

Çözümler:

Kesin sayısal değerler için decimal.Decimal kullanın:

from decimal import Decimal

cursor.execute("CREATE TABLE #PriceDemo (ListPrice DECIMAL(10,2))")
# Preserve full precision
cursor.execute(
    "INSERT INTO #PriceDemo (ListPrice) VALUES (%(list_price)s)",
    {"list_price": Decimal("19.99")}
)

Unicode kodlama sorunları

Belirti -leri:

Özel karakterler karışık görünür veya hatalara yol açar.

Çözümler:

  1. Veritabanınızdaki Unicode verileri için NVARCHAR sütunlarını kullanın

  2. Dizileri doğrudan geçirin - sürücü kodlamayı yönetir:

    cursor.execute("CREATE TABLE #UnicodeDemo (Name NVARCHAR(50))")
    cursor.execute("INSERT INTO #UnicodeDemo (Name) VALUES (%(name)s)", {"name": "日本語"})
    cursor.execute("SELECT Name FROM #UnicodeDemo")
    print(cursor.fetchone())
    

Performans sorunları

Yavaş sorgu yürütme

Olası nedenler ve çözümler:

  • Eksik indeksler: SSMS'de sorgu yürütme planını kontrol edin.

  • Büyük sonuç kümeleri: Yerine fetchmany()kullanınfetchall():

    cursor.arraysize = 1000
    while True:
         rows = cursor.fetchmany()
         if not rows:
             break
         process_rows(rows)
    
  • Bağlantı havuzu devre dışı: Havuzlamayı etkinleştirin:

    import mssql_python
    mssql_python.pooling(max_size=20, idle_timeout=300)
    

Büyük sonuçlarda bellek sorunları

Belirti -leri:

Python sürecinin belleği tükenir.

Çözümler:

  1. Akış sonuçları , hepsini belleğe yüklemek yerine:

    cursor.execute("SELECT * FROM LargeTable")
    for row in cursor:  # Iterates one row at a time
        process_row(row)
    
  2. Sunucu tarafı sayfalamayı kullanın:

    page_size = 1000
    offset = 0
    while True:
        cursor.execute(
            "SELECT * FROM LargeTable ORDER BY ID "
            "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY",
            (offset, page_size)
        )
        rows = cursor.fetchall()
        if not rows:
            break
        process_rows(rows)
        offset += page_size
    

İşlem sorunları

Otomatik commit ile geçici tablo kapsamı

İşlem geri alındığında bir işlem içinde oluşturulan geçici tablolar (#tablename) kaybolur. Bu, otomatik commit kapalı olduğunda (varsayılan olan) yaygın bir kafa karışıklığı kaynağıdır:

conn = mssql_python.connect(connection_string)  # autocommit=False by default
cursor = conn.cursor()

cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")

# If the connection rolls back (explicit or on error), #TempData disappears
conn.rollback()

# This fails: Invalid object name '#TempData'
cursor.execute("SELECT * FROM #TempData")

Düzeltme: Geçici bir tablo oluşturduktan hemen sonra commit yapın veya otomatik commit modunu kullanın:

cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
conn.commit()  # Lock in the table definition

cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")
conn.commit()

Otomatik commit modunu gerektiren DDL ifadeleri, örneğin CREATE DATABASE, açık bir işlem içinde başarısız olur. Bunları çalıştırmadan önce autocommit'i etkinleştirin:

conn.autocommit = True
cursor.execute("CREATE DATABASE TestDB")
conn.autocommit = False

İşlem yapılmadı

Belirti -leri:

Bağlantı kapatıldıktan sonra veri değişiklikleri devam etmiyor.

Çözüm:

autocommit=False ile (varsayılan olarak), commit() çağırmanız gerekir:

cursor.execute("CREATE TABLE #Products (Name NVARCHAR(100))")
cursor.execute("INSERT INTO #Products (Name) VALUES (%(name)s)", {"name": "Widget"})
conn.commit()  # Don't forget this!

Ya da otomatik commit modunu kullanın:

conn = mssql_python.connect(connection_string, autocommit=True)

Kilitlenme hataları

Belirti -leri:

OperationalError: [40001] (1205) Transaction ... was deadlocked on lock resources with another process

Çözüm:

Yeniden deneme mantığı (bkz. Tekrar deneme mantığı) anında hatayla ilgilenir, ancak tekrarlayan çıkmazlar bir tasarım sorunu olduğunu gösterir. Temel nedeni düzeltmek için, deadlock grafiğini yakalayın ve hangi ifadelerin ve kilit türlerinin dahil olduğunu analiz edin. Yaygın çözümler arasında, rakip işlemlerin aynı sırada kilitler elde etmesi için yeniden sıralama, işlem kapsamını azaltmak ve kilit süresini azaltmak için uygun indeksler eklemek yer alır.

Deadlock analizine dair ayrıntılı bir açıklama için Kilitlenmeler rehberine bakın. Azure SQL Veritabanı kullanıyorsanız, Kilitlenme durumlarını analiz etme ve önleme konusuna bakın.

Toplu yükleme sorunları

Toplu kopide sırasında kısıtlama ihlalleri

Belirti -leri:

RuntimeError: CHECK constraint ... Conflict occurred in database ...
RuntimeError: Cannot insert duplicate key ... violation of PRIMARY KEY constraint

Neden:

Toplu veri, tablo kısıtlamalarını (birincil anahtar, tekiz, CHECK veya yabancı anahtar) ihlal eder.

Düzeltme:

Yüklemeden önce verileri doğrulayın. Büyük veri kümeleri için önce bir hazırlama tablosuna yükleyin, ardından hedef tabloyla birleştirin:

# Load into staging, then validate
cursor.execute("CREATE TABLE ##Staging (ID INT, Name NVARCHAR(100))")
cursor.bulkcopy("##Staging", rows)

# Check for duplicates before merging
cursor.execute("""
    SELECT s.ID FROM ##Staging s
    INNER JOIN dbo.Target t ON s.ID = t.ID
""")
dupes = cursor.fetchall()
if dupes:
    print(f"Skipping {len(dupes)} duplicate rows")

# Insert only non-duplicate rows
cursor.execute("""
    INSERT INTO dbo.Target (ID, Name)
    SELECT s.ID, s.Name FROM ##Staging s
    WHERE NOT EXISTS (SELECT 1 FROM dbo.Target t WHERE t.ID = s.ID)
""")
conn.commit()

Aşama tablolarıyla upsert desenleri için bkz. Veri yükleme ve hareket desenleri.

Sütun eşleme hataları

Belirti -leri:

RuntimeError: Bulk copy failure - column count mismatch

Neden:

Verinizdeki sütun sayısı hedef tablonun sütun sayısıyla eşleşmiyor ya da sütunlar yanlış sırada.

Düzeltme:

Verilerinizin, sıra ve sayı bakımından tablo şemasıyla tam olarak eşleştiğinden emin olun:

# Check the target table schema
cursor.execute("""
    SELECT COLUMN_NAME, DATA_TYPE
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'MyTable'
    ORDER BY ORDINAL_POSITION
""")
for col in cursor.fetchall():
    print(col)

# Match your data to the column order
rows = [
    (1, "Widget", Decimal("19.99")),  # Must match table column order
    (2, "Gadget", Decimal("29.99")),
]
cursor.bulkcopy("dbo.MyTable", rows)

Toplu kopyalama sırasında tip uyumsuzlukları

Belirti -leri:

Veri yüklenir ancak değerler kısaltılmış, yuvarlanmış veya yanlıştır.

Neden:

Python değerleri hedef sütun tipleriyle tam olarak eşleşmez. Yaygın durumlar: decimal sütunlarına yüklenen float değerler (hassasiyet kaybı) veya sabit uzunluklu sütunlara yüklenen aşırı uzun dizeler.

Düzeltme:

Şemanıza uyan doğru Python türlerini kullanın:

from decimal import Decimal

# Use Decimal for decimal/numeric columns, not float
rows = [
    (1, "Widget", Decimal("19.99")),  # Correct
    # (1, "Widget", 19.99),           # Avoid: float loses precision
]
cursor.bulkcopy("dbo.Products", rows)

Numpy tür bağlama hataları

Belirti -leri:

Numpy tamsayı veya float tipleri kullanıldığında parametreler sessizce başarısız olur veya veri tipi hatalarını artırır.

Neden:

numpy.int64 ve numpy.int32 gibi NumPy türleri, NumPy 2.x'te isinstance(x, int) kontrolünden geçmez. Sürücünün tip çıkarımı onları tanımaz, bu da beklenmedik davranışlara yol açar.

Düzeltme:

Numpy değerleri bağlamadan önce yerel Python tiplerine dönüştürün:

import numpy as np

# Convert individual values
cursor.execute("SELECT * FROM Production.Product WHERE ProductID = %(product_id)s", {"product_id": int(np.int64(42))})

# Convert DataFrame values
for _, row in df.iterrows():
    cursor.execute(
        "INSERT INTO #Orders (ProductID, Qty) VALUES (%(product_id)s, %(qty)s)",
        {"product_id": int(row["ProductID"]), "qty": int(row["Qty"])}
    )

Daha büyük veri setleri için, tip dönüşümünü dahili olarak yöneten Arrow veya pandas entegrasyon yollarını kullanın.

Geçici tablolarla toplu kopyalama

Belirti -leri:

cursor.bulkcopy("#TempTable", data), RuntimeError: Invalid object name '#TempTable' yükseltir.

Neden:

bulkcopy() metaveri arama sınırlamaları nedeniyle oturum geçici tablolarını (#tablename) çözemiyor. Genel geçici tablolar (##tablename) ve kalıcı tablolar çalışır.

Düzeltme:

Küresel bir geçici tablo veya normal bir aşama tablosu kullanın:

# Global temp table (visible to all sessions, dropped when last session disconnects)
cursor.execute("CREATE TABLE ##Staging (ID INT, Name NVARCHAR(50))")
cursor.bulkcopy("##Staging", rows)

# Or use a permanent staging table
cursor.execute("CREATE TABLE dbo.Staging (ID INT, Name NVARCHAR(50))")
cursor.bulkcopy("dbo.Staging", rows)

Oturum geçici tablosu tercih edilen küçük veri setleri için, bunun yerine şunları kullanın executemany() :

cursor.execute("CREATE TABLE #Staging (ID INT, Name NVARCHAR(50))")
cursor.executemany("INSERT INTO #Staging (ID, Name) VALUES (?, ?)", rows)

Konteyner ve CI sorunları

Linux'ta eksik sistem kütüphaneleri

Belirti -leri:

ImportError: libltdl.so.7: cannot open shared object file: No such file or directory
ImportError: libkrb5.so.3: cannot open shared object file

Düzeltme:

Gerekli sistem paketlerini kurun. Paketler dağılıma göre farklılık gösterir:

Distribution Yükle komutu
Ubuntu / Debian sudo apt-get install libltdl7 libkrb5-3 libgssapi-krb5-2
Red Hat / Fedora sudo dnf install libtool-ltdl krb5-libs
Alpine apk add libltdl krb5-libs

Dockerfile örnekleri için bkz. Konteyner ve yerel geliştirme.

Kurulumdan sonra macOS SSL hataları

Belirti -leri:

macOS'tan bağlanırken, özellikle Apple Silicon'da SSL ile ilgili hatalar.

Düzeltme:

Homebrew üzerinden OpenSSL kur ve linker bayraklarını ayarla:

brew install openssl
export LDFLAGS="-L/opt/homebrew/opt/openssl/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openssl/include"

Tanılama araçları

Sürücü kaydını etkinleştir

Sorun giderme için kapsamlı DEBUG log'unu etkinleştirmek için kullanın mssql_python.setup_logging() . SQL ifadeleri, parametreler, dahili ODBC işlemleri ve bağlantı durumu değişiklikleri dahil olmak üzere tüm sürücü işlemleri kaydedilir.

import mssql_python

# Enable logging to file (default)
mssql_python.setup_logging()

# Output to stdout (useful for CI/CD and containers)
mssql_python.setup_logging(output='stdout')

# Output to both file and stdout
mssql_python.setup_logging(output='both')

# Custom log file path (must use .txt, .log, or .csv extension)
mssql_python.setup_logging(log_file_path="/var/log/myapp/mssql.log")

Log dosyaları CSV biçiminde yazılır ve beş yedek saklanarak 512 MB'ta otomatik olarak rotasyona girer. Şifreler ve erişim tokenları gibi hassas veriler otomatik olarak log çıkışında temizlenir.

Sürücü kayıtlarının yanına kendi günlük kayıtlarınızı eklemek için şunları kullanın driver_logger:

from mssql_python.logging import driver_logger

mssql_python.setup_logging()

driver_logger.debug("[App] Starting data processing")
driver_logger.error("[App] Failed to process record")
# Your entries appear in the same file with the same format

Caution

Loglama performans ek yüküne neden olur. Sadece sorun giderken etkinleştirin, varsayılan olarak üretimde değil.

Sürücü bilgisini alın

Aktif bir bağlantıdan sürücü sürümünü ve sunucu detaylarını alın:

import mssql_python

conn = mssql_python.connect(connection_string)

# Driver version
print(f"Version: {mssql_python.__version__}")

# Server information
print(f"Server name: {conn.getinfo(mssql_python.SQL_SERVER_NAME)}")
print(f"Database name: {conn.getinfo(mssql_python.SQL_DATABASE_NAME)}")

Bağlantı durumunu denetleme

İşleme başlamadan önce bağlantının hala açık olup olmadığını test edin:

try:
    cursor = conn.cursor()
    cursor.execute("SELECT 1")
    print("Connection is open")
except mssql_python.Error:
    print("Connection is closed or broken")

Hızlı referans: Yaygın hatalar

Error SQLSTATE Yaygın neden Hızlı düzeltme
İstemci bağlantı kuramıyor 08001 Sunucuya ulaşılamıyor Sunucu adı/portu kontrol edin
Oturum açılamadı 28000 Yanlış belgeler Kullanıcı adı/şifreyi doğrulayın
Zaman aşımı süresi doldu HYT00/HYT01 Yavaş ağ Zaman aşımını artırın
Geçersiz nesne adı 42S02 Yanlış tablo/şema Tam nitelikli isimler kullanın
Söz dizimi hatası 42000 SQL hatası Parametreli sorguları kullanma
Kısıtlama ihlali 23000 FK/PK ihlali Veri bütünlüğünü kontrol edin
Kilitlenme 40001 Kilitleme çekişmesi Tekrar dene, ardından deadlock grafiğini analiz et