Команда выполнения курсора преждевременно завершает работу без ошибок для продолжительной хранимой процедуры? - PullRequest
0 голосов
/ 25 февраля 2020

У вас есть скрипт pyodb c, который должен выполнять хранимую процедуру на сервере MS SQL, но в середине работы он без ошибок отключается.

У меня есть pyodb c, который подключается к серверу MS SQL (2012), запускает хранимую процедуру (которая выполняет несколько других подчиненных хранимых процедур), которая обычно длится около 45 минут, но при запуске через pyodb c кажется, что она выходит после определенного количества времени (хотя никогда точно не соответствует тому, как долго), когда он просто завершается без предупреждения или ошибки ( не происходит при запуске вручную на самом сервере MS SQL , поэтому я думаю, что "SET ANSI_WARNINGS OFF" "это отлично ). Добавление отладочных операторов печати к подчиненным хранимым процедурам, кажется, подтверждает это: выполнение, похоже, просто заканчивается в середине выполнения (обычно через 25-26 минут). Код выглядит так ...

cnxn = pyodbc.connect(f"DSN={CONFS['odbc_dsn']};"
                      f"DATABASE={'mydb'};"
                      f"UID={CONFS['username']};PWD={CONFS['password']};"
                      f"MultipleActiveResultSets=True;",
                      autocommit=True)
cursor = cnxn.cursor()

print("\n\n\nRunning web reporting processes...")
stored_procs = [
    "mydb..some_initialization_stuff",
    "mydb..long_running_stored_proc"
]
cursor.commit()
for sp in stored_procs:
    print(f"\n\t[{datetime.datetime.now()}] Running stored procedure {sp}")
    cursor.execute(f"SET ANSI_WARNINGS OFF; exec {sp}")
    # cursor.commit()
    print(f"\t[{datetime.datetime.now()}] stored procedure {sp} completed")
    # print(cursor.fetchall())
cursor.close()
cnxn.close()

Кто-нибудь с большим опытом работы с pyodb c знает, что может быть причиной этого? Любая другая информация / указать c шаги отладки, чтобы улучшить этот вопрос?

1 Ответ

0 голосов
/ 26 февраля 2020

Задав вопрос на странице Pyodb c github , причина в основном: ...

При обработке результатов batch, SQL Сервер заполняет выходной буфер соединения результирующими наборами, созданными пакетом . Эти результирующие наборы должны обрабатываться клиентским приложением. Если вы выполняете большой пакет с несколькими наборами результатов, SQL Сервер заполняет этот выходной буфер до тех пор, пока он не достигнет внутреннего предела, и не сможет продолжить обработку большего количества наборов результатов . В этот момент управление возвращается клиенту. Когда клиент начинает использовать наборы результатов, SQL Сервер снова начинает выполнение пакета, поскольку в буфере вывода теперь есть доступная память.

Вы можете либо ...

Метод 1: Flu sh все выходные наборы результатов ...

или

Метод 2: Добавить оператор SET NOCOUNT ON в начало вашей партии ...

, поэтому использование

cursor.execute(f"SET NOCOUNT ON; exec {sp}")

сработало для меня.

(Не уверен, что метод 1 является вариантом в моем случае, так как мы выполняем только одну большую хранимую процедуру (которая вызывает другие хранимые процедуры) и не уверен, есть ли способ получить буфер flu sh в середине этого, но если есть способ, пожалуйста, дайте мне знать).

...