Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Диагностика и устранение распространённых проблем при использовании драйвера 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 | Конкуренция за блокировку | Попробуйте снова, затем проанализируйте график тупиков |