Большая транзакция SQL Server, затем случайные тайм-ауты команд

#sql-server #transactions

#sql-сервер #транзакции

Вопрос:

У меня есть пакетный процесс, который импортирует большие объемы данных. Я делаю это, читая большой текстовый файл и анализируя, а затем выполняя вставки, обновления и удаления в соответствии с данными. Это простые инструкции, выполняемые как хранимые процедуры. Пакет вызовов хранимых процедур помещается в транзакцию, чтобы убедиться, что файл полностью обработан, прежде чем двигаться дальше. Пакетный импорт выполняется раз в неделю. Если клиент отстает, может быть несколько крупных транзакций подряд. Когда это происходит, я иногда получаю тайм-ауты команд в транзакциях после первой. Я увеличил время ожидания команды до 120 секунд. Пока работает нормально, но на медленном компьютере это может быть не так. Я заметил, что тайм-аут часто возникает на:

 Update <table> set <columns> where <pk = some value>
  

Я подумал, что, возможно, SQL все еще обновляет индексы в фоновом режиме. Есть идеи о том, что происходит?

Я понимаю, что мог бы использовать что-то вроде SqlBulkCopy, но сейчас это не вариант.

Спасибо, Скотт

Комментарии:

1. Вероятно, у вас где-то есть блокировка. Это ваша основная производственная транзакционная база данных, поскольку другие люди запрашивают ее, когда вы ее обновляете? Если это так, ваша транзакция может блокировать ее.

2. Я забыл упомянуть, что это фактически однопользовательская база данных. Мое тестирование, где я получаю тайм-аут, — это машина разработчика, на которой нет других пользователей. Как ни странно, увеличение времени ожидания привело к устранению проблемы.

Ответ №1:

Выполняется ли ваш sproc построчно или он выполняет вставки, ОБНОВЛЕНИЯ и так далее на основе наборов? Ответ на этот вопрос станет важным несколькими абзацами ниже.

Но, во-первых, проблема с увеличением времени ожидания — это проблема n 1, независимо от того, как долго вы это делаете, этот случай все равно будет повторяться. Таким образом, увеличение времени ожидания не является постоянным решением для сна по ночам, как у младенца. Гораздо лучше устранить необходимость в тайм-ауте, разбив задание.

Первое, что вы делаете, это устраняете эту завершающую транзакцию. Ресурсы, необходимые для поддержания блокировок, увеличиваются по мере увеличения количества строк в операции, так что пакетные операции, подобные этой, часто выполняются быстрее, если разбить их на более мелкие этапы, требующие меньших транзакций.

Следующий шаг, поскольку у вас больше нет этой завершающей транзакции, заключается в том, чтобы убедиться, что каждый отдельный шаг может быть безопасно перезапущен в случае неудачного задания, независимо от того, где находился процесс в момент сбоя. Это называется «идемпотентным», если вы хотите быть причудливым, или «перезапускаемым», если вы хотите использовать простой английский.

Теперь мы возвращаемся к вопросу, выполняется ли ваш sproc построчно или он выполняет ВСТАВКИ, которые влияют на многие строки, затем ОБНОВЛЕНИЯ и так далее.

Пошаговый АНАЛИЗ: самый простой, хотя, вероятно, и самый медленный. Поместите текстовый файл в таблицу «ВХОДЯЩИЕ» и добавьте столбец «Обработано», который равен Y / N. При переходе строка за строкой вы выполняете ВСТАВКУ, ОБНОВЛЕНИЕ или УДАЛЕНИЕ, затем обновляете строку в таблице входящих как обработанную = Y. Если вы отключите подключение на любом этапе, sproc просто возобновит просмотр необработанных строк, пока их не останется ни одной. Это дает вам тот же эффект, что и большая транзакция переноса, без накладных расходов. Вы можете запускать десятки файлов подряд, и время ожидания сервера никогда не истечет.

НА ОСНОВЕ НАБОРА РЕГИСТРОВ: Если вы используете DML на основе наборов, то вы изменяете ВСТАВКУ таким образом, чтобы она извлекалась из таблицы входящих сообщений и ВСТАВЛЯЛАСЬ в целевую таблицу для всех строк, которых там еще нет. Это делает его доступным для повторного запуска. Инструкции DELETE не нуждаются в этой проверке, если вы повторно запустите УДАЛЕНИЕ на основе набора, и оно уже запущено, оно просто не найдет ничего для удаления. ОБНОВЛЕНИЕ в основном такое же, как УДАЛЕНИЕ в.

Это общий совет, основанный на том, что вы заявили о своей проблеме. Чтобы уточнить, мне нужно было бы узнать больше об этом процессе.

Ответ №2:

Я бы посмотрел на фрагментацию ваших индексов и при необходимости перестроил их.

Также я бы запустил ваши запросы в SSMS и включил включить фактический план выполнения и посмотреть, есть ли у вас какие-либо проблемы.

Комментарии:

1. Вероятно, это будет моим краткосрочным решением.

Ответ №3:

Сначала вам нужно выяснить, что является причиной тайм-аута. Как и при любом исследовании производительности SQL Server, наилучшим подходом является методология ожидания и очередей. В принципе, вам нужно посмотреть на wait_type , wait_time и wait_resource в sys.dm_exec_requests для сеанса, который выполняет UPDATE . Это покажет, что блокирует / замедляет ОБНОВЛЕНИЕ, и в соответствии с этим выводом вы можете выполнить соответствующее действие / решение. Если рискну предположить, выстрел в темноте, ты кидаешься в журнале авто-рост событий в процессе тестирования. Тем не менее, правильное решение — сначала измерить, а затем сократить: исследовать, чтобы определить основную причину тайм-аута, и только после этого приступить к изменениям.