Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Диагностика и устранение распространённых проблем при использовании драйвера mssql-python для подключения к SQL Server, База данных SQL Azure, Управляемый экземпляр SQL Azure и SQL Database в Microsoft Fabric.
Проблемы с установкой
Установка pip завершается с ошибкой или выполняется сборка из исходного кода
Симптомы:
error: Microsoft Visual C++ 14.0 or greater is required
ERROR: Failed building wheel for mssql-python
Возможные причины и решения:
Нет готового колеса для вашей платформы
- Проверьте, что у вас поддерживаемая версия Python (версии 3.10 и выше) и платформа. См. Жизненный цикл поддержки для матрицы совместимости. Обновите pip перед установкой с помощью
pip install --upgrade pip. Для повторяемых командных сред используйте заблокированный рабочий процесс в повторяемых развертываниях или шаблоны контейнеров в контейнере и локальной разработке , чтобы уменьшить локальный дрейф машин.
- Проверьте, что у вас поддерживаемая версия Python (версии 3.10 и выше) и платформа. См. Жизненный цикл поддержки для матрицы совместимости. Обновите pip перед установкой с помощью
Виртуальная среда не активирована
- Сначала активируйте виртуальную среду. Установка в систему Python может вызвать ошибки с правами или конфликты.
python -m venv .venv .venv\Scripts\activate pip install mssql-python
-
Отсутствующие системные библиотеки Linux
- Драйвер требует небольшого набора системных библиотек на Linux. См. Зависимости для конкретной платформы, чтобы узнать, какие пакеты нужно установить.
Конфликтующие установки драйверов
Симптомы:
Ошибки импорта или неожиданное поведение после установки mssql-python вместе с pyodbc в одной и той же среде.
Исправление:
mssql-python и pyodbc могут сосуществовать. Если вы видите конфликты, создайте чистую виртуальную среду:
python -m venv .venv --clear
.venv\Scripts\activate
pip install mssql-python
Проблемы с подключением
Не удаётся подключиться к серверу
Симптомы:
OperationalError: [08001] (0) Client unable to establish connection
Возможные причины и решения:
Сервер недоступен
- Проверьте, что имя сервера и порт верны.
- Проверьте сетевое подключение:
ping servernameилиtelnet servername 1433. - Убедитесь, что файрвол позволяет исходящие соединения на порте 1433.
SQL Server не работает
- Проверьте, запущен ли сервис SQL Server.
- Для именованных экземпляров проверьте, работает ли сервис SQL Server Browser.
Azure SQL firewall rules
- Добавьте свой клиентский IP в правила брандмауэра Azure SQL в портале Azure.
- Для Управляемый экземпляр SQL Azure убедитесь, что вы подключаетесь из разрешённой сети.
# 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}")
Сбой входа
Симптомы:
OperationalError: [28000] (18456) Login failed for user 'username'.
Возможные причины и решения:
Несоответствие режимов аутентификации
- Для База данных SQL Azure, Управляемый экземпляр SQL Azure и базы данных SQL в Fabric предпочтительно использовать режим Microsoft Entra, например
Authentication=ActiveDirectoryDefault. - Если вы намеренно используете SQL-аутентификацию, убедитесь, что сервер это разрешает и что вы используете правильный формат входа для этой конечной точки.
- Для База данных SQL Azure, Управляемый экземпляр SQL Azure и базы данных SQL в Fabric предпочтительно использовать режим Microsoft Entra, например
Неправильные учетные данные SQL-аутентификации
- Проверьте имя пользователя и пароль.
- Для Azure SQL укажите полное имя пользователя:
username@servername.
User не существует в базе данных
- Проверьте, что пользователь имеет доступ к указанной базе данных.
- Проверьте, связан ли вход с пользователем базы данных.
Аутентификация не настроена
- Используйте аутентификацию Microsoft Entra (рекомендую):
Authentication=ActiveDirectoryDefault. - Если вы ищете неполадки с локальным SQL Server, который должен поддерживать SQL-аутентификацию, проверьте, использует ли SQL Server смешанную аутентификацию.
- Используйте аутентификацию Microsoft Entra (рекомендую):
Время соединения истекло
Симптомы:
OperationalError: [HYT00] (0) Timeout expired
OperationalError: [HYT01] (0) Connection timeout expired
Возможные причины и решения:
Сервер медленно отвечает
- Увеличьте тайм-аут соединения:
conn = mssql_python.connect(connection_string, timeout=60)Задержка сети
- Проверьте путь сети к серверу.
- Рассмотрите возможность использования более короткого сетевого пути или VPN.
Сервер под большой нагрузкой
- Попробуйте подключиться в непиковые часы.
- Свяжитесь с администратором вашей базы данных.
Ошибки SSL-сертификата
Симптомы:
OperationalError: [08001] SSL Provider: The certificate chain was issued by an authority that is not trusted
Решения:
Во-первых, предпочитайте проверенный сертификат или локальные паттерны разработки в контейнерной и локальной разработке. Используйте TrustServerCertificate=yes только для локальной разработки при работе с сервером, который вы контролируете.
Для разработки и тестирования с самоподписанным сертификатом:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
"TrustServerCertificate=yes;" # Don't use in production
)
Предостережение
TrustServerCertificate=yes — это резервный вариант, используемый только локально. Не переносите это в общие контейнеры разработки, CI-конвейеры или производственные развертывания. Для более широких рекомендаций см. раздел Шифрование и сертификаты.
Для производства убедитесь, что установлены соответствующие сертификаты и используйте:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
"HostnameInCertificate=<server>.domain.com;"
)
Проблемы с выполнением запросов
Таблица или объект не найден.
Симптомы:
ProgrammingError: [42S02] (208) Invalid object name 'TableName'.
Возможные причины и решения:
Неправильный контекст базы данных
# Ensure you're connected to the correct database cursor.execute("SELECT DB_NAME()") print(cursor.fetchone()[0])Схема не указана
# Use fully qualified name cursor.execute("SELECT * FROM dbo.TableName")Таблицы не существует
# Check if table exists cursor.execute(""" SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TableName' """)
Синтаксическая ошибка
Симптомы:
ProgrammingError: [42000] (102) Incorrect syntax near '...'.
Решения:
Сначала проверьте SQL в SSMS для проверки синтаксиса
Проверьте выход строк — используйте параметризованные запросы:
# 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})
Ошибки параметров
Симптомы:
ProgrammingError: [07001] Wrong number of parameters
Решения:
Подсчитайте заполнители и параметры — их количество должно совпадать
Выберите правильный стиль параметров:
# 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())
Проблемы с типами данных
Ошибки конвертации времени и даты
Симптомы:
DataError: [22007] Invalid datetime format
Решения:
Используйте объекты datetime в Python вместо строк:
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())
Проблемы с десятичной точностью
Симптомы:
Числа выглядят усечёнными или округлёнными неправильно.
Решения:
Использование decimal.Decimal для точных числовых значений:
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
Симптомы:
Особые символы выглядят искажёнными или вызывают ошибки.
Решения:
Используйте столбцы NVARCHAR для данных Unicode в вашей базе данных
Передавайте строки напрямую — драйвер занимается кодированием:
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())
Проблемы с производительностью
Медленное выполнение запросов
Возможные причины и решения:
Отсутствующие индексы: проверьте план выполнения запросов в SSMS.
Большие наборы результатов: используйте
fetchmany()вместоfetchall():cursor.arraysize = 1000 while True: rows = cursor.fetchmany() if not rows: break process_rows(rows)Пул соединений отключен: Включите пул соединений:
import mssql_python mssql_python.pooling(max_size=20, idle_timeout=300)
Проблемы с памятью при больших результатах
Симптомы:
Процессу Python не хватает памяти.
Решения:
Результаты потока вместо того, чтобы загружать всё в память:
cursor.execute("SELECT * FROM LargeTable") for row in cursor: # Iterates one row at a time process_row(row)Используйте страницирование на стороне сервера:
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
Вопросы транзакций
Область видимости временной таблицы при автокоммите
Временные таблицы (#tablename), созданные внутри транзакции, исчезают при откате транзакции. Это часто вызывает путаницу, когда автокоммит отключён (по умолчанию):
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")
Исправление: Зафиксируйте транзакцию сразу после создания временной таблицы или используйте режим автокоммита:
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()
DDL-операторы, требующие режима автофиксации, например CREATE DATABASE, не работают внутри открытой транзакции. Настройте автокоммит перед их запуском:
conn.autocommit = True
cursor.execute("CREATE DATABASE TestDB")
conn.autocommit = False
Сделка не была совершена
Симптомы:
Изменения данных не сохраняются после закрытия соединения.
Solution:
С autocommit=False (по умолчанию) вы должны вызвать commit():
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!
Или используйте режим автокоммита:
conn = mssql_python.connect(connection_string, autocommit=True)
Ошибки взаимоблокировки
Симптомы:
OperationalError: [40001] (1205) Transaction ... was deadlocked on lock resources with another process
Solution:
Повторная логика (см. логику повторного попробовки) обрабатывает немедленный сбой, но повторяющиеся тупики указывают на проблему проектирования. Чтобы устранить коренную причину, зафиксируйте граф тупиков и проанализируйте, какие операторы и типы замков задействованы. Распространённые способы устранения включают изменение порядка операций так, чтобы конкурирующие транзакции получали блокировки в одной и той же последовательности, сокращение области транзакции и добавление подходящих индексов для уменьшения времени удержания блокировок.
Для полного обзора анализа тупиков смотрите руководство по Deadlocks. Если вы используете База данных SQL Azure, см. Анализ и предотвращение взаимоблокировок.
Проблемы с массовой нагрузкой
Нарушения ограничений во время массового копирования
Симптомы:
RuntimeError: CHECK constraint ... Conflict occurred in database ...
RuntimeError: Cannot insert duplicate key ... violation of PRIMARY KEY constraint
Причина:
Данные в вашем пакете нарушают ограничения таблицы (первичный ключ, уникальный, CHECK или внешний ключ).
Исправление:
Проверьте данные перед загрузкой. Для больших наборов данных сначала загрузите их в промежуточную таблицу, а затем выполните слияние с целевой таблицей:
# 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()
Для сценариев upsert с промежуточными таблицами см. Шаблоны загрузки и перемещения данных.
Ошибки отображения столбцов
Симптомы:
RuntimeError: Bulk copy failure - column count mismatch
Причина:
Количество столбцов в ваших данных не совпадает с количеством столбцов целевой таблицы, или столбцы расположены в неправильном порядке.
Исправление:
Убедитесь, что ваши данные точно соответствуют схеме таблицы по порядку и количеству:
# 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)
Несоответствия типов при массовом копировании
Симптомы:
Данные загружаются, но значения усечаны, округлены или некорректны.
Причина:
Значения Python не могут быть однозначно сопоставлены с типами целевого столбца. Распространённые случаи: значения float, загруженные в столбцы decimal (потеря точности), или слишком длинные строки, загруженные в столбцы фиксированной длины.
Исправление:
Используйте правильные типы Python, соответствующие вашей схеме:
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
Симптомы:
При использовании целочисленных типов или типов с плавающей точкой NumPy параметры либо молча не срабатывают, либо вызывают ошибки типа данных.
Причина:
Типы NumPy, такие как numpy.int64 и numpy.int32, не проходят isinstance(x, int) в NumPy 2.x. Механизм вывода типов драйвера не распознаёт их, из-за чего возникает непредсказуемое поведение.
Исправление:
Преобразуйте значения numpy в родные типы Python перед привязкой:
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"])}
)
Для больших наборов данных используйте пути интеграции Arrow или pandas , которые выполняют внутреннее преобразование типов.
Массовое копирование с временными таблицами
Симптомы:
cursor.bulkcopy("#TempTable", data) вызывает RuntimeError: Invalid object name '#TempTable'.
Причина:
bulkcopy() не может обрабатывать временные таблицы сеанса (#tablename) из-за ограничений при поиске метаданных. Глобальные временные таблицы (##tablename) и постоянные таблицы работают.
Исправление:
Используйте глобальную временную таблицу или обычную таблицу стадирования:
# 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)
Для небольших наборов данных, где предпочтительнее временная таблица сессий, используйте executemany() вместо этого:
cursor.execute("CREATE TABLE #Staging (ID INT, Name NVARCHAR(50))")
cursor.executemany("INSERT INTO #Staging (ID, Name) VALUES (?, ?)", rows)
Вопросы контейнера и CI
Отсутствующие системные библиотеки в Linux
Симптомы:
ImportError: libltdl.so.7: cannot open shared object file: No such file or directory
ImportError: libkrb5.so.3: cannot open shared object file
Исправление:
Установите необходимые системные пакеты. Пакеты различаются по распределению:
| Distribution | Команда установки |
|---|---|
| Ubuntu / Debian | sudo apt-get install libltdl7 libkrb5-3 libgssapi-krb5-2 |
| Red Hat / Fedora | sudo dnf install libtool-ltdl krb5-libs |
| Алпайн | apk add libltdl krb5-libs |
Для примеров Dockerfile см. раздел Container and local development.
Ошибки macOS SSL после установки
Симптомы:
Ошибки, связанные с SSL, при подключении с macOS, особенно на Apple Silicon.
Исправление:
Установите OpenSSL через Homebrew и установите флаги linker:
brew install openssl
export LDFLAGS="-L/opt/homebrew/opt/openssl/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openssl/include"
Средства диагностики
Включить логирование драйверов
Используйте mssql_python.setup_logging() для включения комплексного DEBUG-логирования для устранения неполадок. Все операции драйвера регистрируются в журнале, включая операторы SQL, параметры, внутренние операции ODBC и изменения состояния соединения.
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")
Файлы журналов записываются в формате CSV, и при достижении 512 МБ для них автоматически выполняется ротация с сохранением пяти резервных копий. Конфиденциальные данные, такие как пароли и токены доступа, автоматически очищаются в выходе журналов.
Чтобы добавить свои записи в журнале вместе с логами водителей, используйте 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
Предостережение
Логирование связано с накладными расходами по производительности. Включайте его только при устранении неполадок, а не в продакшене по умолчанию.
Получите информацию о водителях
Получите версию драйвера и данные сервера из активного соединения:
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)}")
Проверка состояния подключения
Проверьте, остаётся ли соединение открытым, прежде чем выполнять операции:
try:
cursor = conn.cursor()
cursor.execute("SELECT 1")
print("Connection is open")
except mssql_python.Error:
print("Connection is closed or broken")
Краткая справка: Распространённые ошибки
| Ошибка | SQLSTATE | Распространенная причина | Быстрое исправление |
|---|---|---|---|
| Клиенту не удается установить подключение | 08001 | Сервер недоступен | Проверьте имя/порт сервера |
| Сбой входа | 28000 | Неправильные удостоверения | Проверьте имя пользователя/пароль |
| Время ожидания истекло. | HYT00/HYT01 | Медленная сеть | Увеличение времени ожидания |
| Недопустимое имя объекта | 42S02 | Неправильная таблица/схема | Используйте полностью квалифицированные имена |
| Синтаксическая ошибка | 42000 | Ошибка SQL | Использование параметризованных запросов |
| Нарушение ограничений | 23000 | Нарушение FK/PK | Проверка целостности данных |
| Deadlock | 40001 | Конкуренция за блокировку | Попробуйте снова, затем проанализируйте график тупиков |