Недавно я перенес платформу ETL с Python 2,7 на 3, а также обновил ее Docker образ с Ubuntu 16.04 до 18.04.
После миграции я столкнулся с действительно странным поведением при попытке отразить SQL Серверные таблицы с использованием SQLAlchemy с драйвером pyodb c.
Изначально я видел это сообщение об ошибке:
[08S01] [FreeTDS][SQL Server]Read from the server failed (20004) (SQLExecDirectW)
Я обновил SQLAlchemy с 0.9.8 до 1.3.10 (я не трогал pyodb c, который был в 3.0.10), поэтому я последовал совету в документации и изменил драйвер pyodb c с FreeTDS 7.0 на Microsoft ODB C Driver 17. Все, что было сделано, это изменило сообщение об ошибке на следующее:
[08S01] [Microsoft][ODBC Driver 17 for SQL Server]TCP Provider: Error code 0x274C (10060) (SQLExecDirectW)
Я подтвердил, что могу войти на сервер, используя i sql, и поэтому я попытался напрямую выполнить запрос, который SQLAlchemy пытается выполнить, чтобы получить информацию о таблице
SELECT
[INFORMATION_SCHEMA].[COLUMNS].[TABLE_SCHEMA]
, [INFORMATION_SCHEMA].[COLUMNS].[TABLE_NAME]
, [INFORMATION_SCHEMA].[COLUMNS].[COLUMN_NAME]
, [INFORMATION_SCHEMA].[COLUMNS].[IS_NULLABLE]
, [INFORMATION_SCHEMA].[COLUMNS].[DATA_TYPE]
, [INFORMATION_SCHEMA].[COLUMNS].[ORDINAL_POSITION]
, [INFORMATION_SCHEMA].[COLUMNS].[CHARACTER_MAXIMUM_LENGTH]
, [INFORMATION_SCHEMA].[COLUMNS].[NUMERIC_PRECISION]
, [INFORMATION_SCHEMA].[COLUMNS].[NUMERIC_SCALE]
, [INFORMATION_SCHEMA].[COLUMNS].[COLUMN_DEFAULT]
, [INFORMATION_SCHEMA].[COLUMNS].[COLLATION_NAME]
FROM
[INFORMATION_SCHEMA].[COLUMNS]
WHERE
[INFORMATION_SCHEMA].[COLUMNS].[TABLE_NAME] = CAST(<table name> AS NVARCHAR(max))
AND [INFORMATION_SCHEMA].[COLUMNS].[TABLE_SCHEMA] = CAST(<schema name> AS NVARCHAR(max))
ORDER BY [INFORMATION_SCHEMA].[COLUMNS].[ORDINAL_POSITION];
Когда я запускаю этот запрос, соединение просто зависает и время ожидания истекает. Я начал играть с запросом и обнаружил, что могу нормально выполнять запросы, если они находятся под определенным ограничением символов. Например:
-- This works (and returns all columns)
SELECT
*
FROM
[INFORMATION_SCHEMA].[COLUMNS]
WHERE
[INFORMATION_SCHEMA].[COLUMNS].[TABLE_NAME] = CAST(<table name> AS NVARCHAR(max))
AND [INFORMATION_SCHEMA].[COLUMNS].[TABLE_SCHEMA] = CAST(<schema name> AS NVARCHAR(max))
ORDER BY [INFORMATION_SCHEMA].[COLUMNS].[ORDINAL_POSITION];
-- This also works
SELECT
[INFORMATION_SCHEMA].[COLUMNS].[TABLE_SCHEMA]
, [INFORMATION_SCHEMA].[COLUMNS].[TABLE_NAME]
, [INFORMATION_SCHEMA].[COLUMNS].[COLUMN_NAME]
, [INFORMATION_SCHEMA].[COLUMNS].[IS_NULLABLE]
, [INFORMATION_SCHEMA].[COLUMNS].[DATA_TYPE]
, [INFORMATION_SCHEMA].[COLUMNS].[ORDINAL_POSITION]
, [INFORMATION_SCHEMA].[COLUMNS].[CHARACTER_MAXIMUM_LENGTH]
FROM
[INFORMATION_SCHEMA].[COLUMNS]
WHERE
[INFORMATION_SCHEMA].[COLUMNS].[TABLE_NAME] = CAST(<table name> AS NVARCHAR(max))
AND [INFORMATION_SCHEMA].[COLUMNS].[TABLE_SCHEMA] = CAST(<schema name> AS NVARCHAR(max))
ORDER BY [INFORMATION_SCHEMA].[COLUMNS].[ORDINAL_POSITION];
-- This causes the connection to hang after adding the line
-- , [INFORMATION_SCHEMA].[COLUMNS].[NUMERIC_PRECISION]
SELECT
[INFORMATION_SCHEMA].[COLUMNS].[TABLE_SCHEMA]
, [INFORMATION_SCHEMA].[COLUMNS].[TABLE_NAME]
, [INFORMATION_SCHEMA].[COLUMNS].[COLUMN_NAME]
, [INFORMATION_SCHEMA].[COLUMNS].[IS_NULLABLE]
, [INFORMATION_SCHEMA].[COLUMNS].[DATA_TYPE]
, [INFORMATION_SCHEMA].[COLUMNS].[ORDINAL_POSITION]
, [INFORMATION_SCHEMA].[COLUMNS].[CHARACTER_MAXIMUM_LENGTH]
, [INFORMATION_SCHEMA].[COLUMNS].[NUMERIC_PRECISION]
FROM
[INFORMATION_SCHEMA].[COLUMNS]
WHERE
[INFORMATION_SCHEMA].[COLUMNS].[TABLE_NAME] = CAST(<table name> AS NVARCHAR(max))
AND [INFORMATION_SCHEMA].[COLUMNS].[TABLE_SCHEMA] = CAST(<schema name> AS NVARCHAR(max))
ORDER BY [INFORMATION_SCHEMA].[COLUMNS].[ORDINAL_POSITION];
Я в полной растерянности относительно того, что происходит. Попытка запустить отражение от старого Docker образа в Ubuntu 16.04 и Python 2.7 работает нормально; Я также могу выполнить запрос, если я подключусь к базе данных через DataGrip. Я попытался использовать pyms sql, и это дает первую ошибку. Есть ли какой-то пакет / зависимость, которую я должен проверять, что может вызвать это? Когда я использовал драйвер FreeTDS, строка подключения имела UseNTLMv2 = true, и я не использую TrustedConnection = Yes с драйвером Microsoft, потому что он хочет, чтобы я настроил Kerberos, и я не хочу go вниз по этой кроличьей норе, если это что-то еще, учитывая, что у драйвера FreeTDS та же проблема.
Это какая-то странная вещь в сети? Я разозлил SQL богов своей гордыней? Есть ли дополнительная информация, которую я должен добавить?