Тайм-аут sql server 2005 истекает в производственной, а не в тестовой среде: почему? - PullRequest
0 голосов
/ 27 августа 2009

В своей среде разработки я стараюсь воссоздать производственную проблему, которую мы сталкиваются с MSSQL 2005. Эта проблема состоит из двух частей:

Проблема

1) Возникает взаимоблокировка, и MSSQL выбирает одно соединение («Соединение X») в качестве «жертвы». 2) Все последующие попытки использовать «Соединение X» терпят неудачу (мы используем пул соединений). MSSQL говорит: «Серверу не удалось возобновить транзакцию»

Из двух, # 2, если более серьезно: так как «соединение X» разбивается каждый Попытка повторного использования "соединения x" с "циклическим перебором" провалилась «случайные» ошибки появляются для пользователя. Мы должны перезагрузить сервер.

Почему я пишу

Однако на данный момент я хочу воссоздать проблему № 1. Я могу создать легко заблокировать.

Но вот моя проблема: в то время как на производстве MSSQL выбирает один соединение (SPID) как «жертва тупика», в моей тестовой среде тупик просто зависает ... и зависает, и зависает. Навсегда? Я не уверен, но я оставил его висеть на ночь, а он все еще висел утром.

Итак, вот вопрос: как я могу заставить sql server "выбрать жертву тупика" при возникновении тупика?

Пока попыток

Я попытался установить параметр «lock_timeout» через URL-адрес jdbc («lockTimeout = 5000»), однако я получил сообщение, отличное от производственного (в тесте «Превышен период ожидания запроса блокировки.» Вместо производственного » Транзакция (ID процесса 59) была заблокирована для ресурсов блокировки другого процесса и была выбрана в качестве жертвы тупика. ")

Некоторые подробности о проблеме № 2

Я исследовал эту проблему "не удалось возобновить транзакцию" и нашел Несколько вещей:

  • неправильная обработка исключений может вызвать эту проблему. Например: код Java делает не закрывайте Statement / PreparedStatement и реализацию драйвера «Соединение» застряло с плохим / устаревшим / старым «идентификатором транзакции»
  • Обновление драйвера jdbc может устранить проблему.

А пока я просто хочу воссоздать тупик и сделать sql server «выбрать жертву тупика».

спасибо заранее!

Приложение A. Техническая среда

Разработка:

  • sql server 2005 с пакетом обновления 3 (9.00.4035.00)
  • драйвер: sqljdbc.jar версия 1.0
  • Jboss 3.2.6
  • jdbc url: jdbc: sqlserver: // <>;

Производство:

  • sql server 2005 SP2 (9.00.3042.00)
  • драйвер: sqljdbc.jar версия 1.0
  • Jboss 3.2.6
  • URL-адрес jdbc: jdbc: sqlserver: // <>;

Приложение B. Шаги для нахождения тупика

  • получить соединение A
  • получить соединение B
  • запустить sql1 с подключением A
  • запустить sql2 с подключением B
  • запустить sql1 с подключением B
  • запустить sql2 с подключением A

где SQL1: обновить имя набора участников = name + 'x' WHERE member_id = 71

SQL2: обновить имя набора участников = name + 'x' WHERE member_id = 72

Ответы [ 4 ]

0 голосов
/ 28 августа 2009

[Это ответ на ответы. Пользовательский интерфейс не позволяет больше «комментариев» на ответы]

Какие запросы выполняются? Что на самом деле вызывает тупик?

В моей тестовой среде я выполнял очень простые запросы:

SQL1: ОБНОВЛЕНИЕ принципала SET name = name + '.' ГДЕ Principal_id = 71

SQL2: ОБНОВЛЕНИЕ принципала SET name = name + '.' ГДЕ Principal_id = 72

Затем выполнил их в порядке хиастика / крест-накрест, то есть без всяких коммитов.

connectionA

 sql1

   connectionB

      sql2

      sql1

 sql2

Это мне кажется базовым примером тупика. Однако, если это «простой замок», а не тупик, пожалуйста, отвлеки меня от этого понятия.

На производстве наш «проблемный запрос» («prodbad») выглядел так:

ОБНОВЛЕНИЕ поста SET lock_flag =? ГДЕ thread_id IN (ВЫБЕРИТЕ thread_id ОТ ПОСТА ГДЕ post_id =?)

Обратите внимание на несколько вещей:

1) Этот «запрос о проблеме» фактически работает. AFAIK это было в этот раз тупик

2) Я подозреваю, что проблема заключается в блокировке страницы, то есть пессимистической блокировке из-за операций чтения в другом месте транзакции

3) Я не знаю, что sql эта транзакция выполнила до этого запроса.

4) Этот запрос является примером "я могу сделать это одним оператором sql" обработка, которая кажется программисту умной, в конечном итоге вызывает гораздо больше операций ввода-вывода, чем выполнение двух запросов:

queryM: ВЫБЕРИТЕ thread_id ОТ ПОСТА ГДЕ post_id =?

queryN: ОБНОВЛЕНИЕ поста SET lock_flag =? ГДЕ thread_id = <>

*> (Мысль - ваши базы данных Dev являются копиями ваших производственных БД?

Если базы данных разработчиков на порядки меньше, чем Prod, ваши запросы могут быть такими же, но> то, что делает SQL «под капотом», будет сильно отличаться.) *

В этом случае БД prod и dev отличаются. «Prod сервер» имел тонны данных. «Dev db» имел мало данных. Запросы были очень разные. Все, что я хотел сделать, это воссоздать тупик.

*> Серверу не удалось возобновить транзакцию ... Почему ?. Вы должны обновить до JDB

C драйвер SQL v2.0, прежде чем что-либо еще. *

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

Напомним:

У меня была «яркая идея», чтобы вызвать простой тупик и посмотреть, было ли мое соединение «сломано / замкнуто / разорвано / и т.д.» Однако тупик вел себя не так, как на производстве.

0 голосов
/ 27 августа 2009

Какие запросы выполняются? Что на самом деле вызывает тупик?

Вы говорите, что у вас есть два соединения A и B. A запускает sql1, затем sql2, а B запускает sql2, а затем sql1. Итак, что за работа (запросы) выполняется? Что еще более важно, где транзакции? Какой уровень изоляции вы используете? Что открывает / закрывает транзакции? (Да, это приводит к сомнению в обработке исключений, используемой вашими драйверами - если они не обнаруживают и не обрабатывают возвращенное сообщение «это не сработало», то вам абсолютно необходимо вернуть их назад и выстрелить - Пули или пенициллин, ваш звонок.)

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

(Подумайте - ваши копии базы данных Dev ваших производственных баз данных? Если базы данных разработчиков на порядки меньше, чем Prod, ваши запросы могут быть такими же, но то, что SQL делает «под капотом», будет сильно отличаться. )

Последняя мысль: SQL будет автоматически обнаруживать и обрабатывать взаимоблокировки (я действительно не думаю, что вы можете отключить это), если у вас работает в течение ночи, я не думаю, что у вас тупик, а просто обычная блокировка / проблема блокировки.

[Опубликовать это сейчас - собираюсь что-то найти, позже зайду.]
[Позже]

Интересно - SQL Server 2005 compact edition не обнаруживает взаимоблокировок, он только делает тайм-ауты. Вы не используете это в Dev, не так ли?

Я не вижу способа "выключить" или иным образом контролировать период ожидания тупика. Я столкнулся с взаимоблокировками только на прошлой неделе, и некоторые произвольные проверки показали, что взаимоблокировки обнаруживаются и разрешаются (для нашего сервера разработки) менее чем за 5 секунд. Похоже, у вас нет тупиков на вашей машине разработчика, просто блокировка. Но поймите, что этот материал трудно проанализировать «администраторам кресел», вам действительно нужно сесть и сделать серьезный анализ того, что происходит внутри системы, когда возникает эта проблема.

0 голосов
/ 27 августа 2009

Объяснение того, почему соединение JDBc входит в неправильное состояние, приводится здесь: Серверу не удалось возобновить транзакцию ... Почему? . Вы должны обновить до JDBC SQL драйвер v2.0 , прежде чем что-либо еще. Ссылка также содержит рекомендации о том, как исправить обработку приложения, чтобы избежать этой ситуации, а главное о том, как избежать смешивания API транзакций JDBC с собственными транзакциями Transact-SQL.

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

Любое расследование тупика должно начинаться с понимания тупика, если вы хотите устранить его. Класс событий Dedlock Graph в Profiler является идеальной отправной точкой. С информацией о графике взаимоблокировки вы можете увидеть, на каких ресурсах происходит взаимоблокировка и какие операторы используются. В большинстве случаев решением является либо исправление порядка обновлений в приложении ( всегда следуют одному и тому же порядку), либо исправление пути доступа (т. Е. Добавление индекса).

Обновление

  • UPDATE .. WHERE key IN (SELECT ...) обычно блокируется, потому что операция не является атомарной. Несколько потоков могут возвращать один и тот же список 1025 * IN, поскольку часть SELECT ничего не блокирует. Это всего лишь предположение, для правильной проверки необходимо посмотреть информацию о взаимоблокировке.

  • Чтобы проверить свой ручной тест на наличие взаимоблокировок, вы должны убедиться, что блокирующие SPID образуют цикл. Посмотрите на SELECT session_id, blocking_session_id FROM sys.dm_exec_requests WHERE blocking_session_id <> 0. Если результат содержит цикл (например, A заблокирован B и B заблокирован A), а сервер не вызывает взаимоблокировку, это ошибка. Тем не менее, вы обнаружите, что список блокировки не образует цикл, будет что-то A заблокировано B и B заблокировано C и C нет в списке, что означает, что вы сделали что-то неправильно тест репро.

0 голосов
/ 27 августа 2009

Вы можете указать приоритет тупика для сеанса, используя

SET DEADLOCK_PRIORITY LOW | MEDIUM | HIGH

Подробнее см. Эту ссылку MSDN .

Вы также можете использовать следующую команду для просмотра открытых транзакций

DBCC OPENTRAN (db_name)

Эта команда может помочь вам определить причину тупика. См. MSDN для получения дополнительной информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...