DataInconsistancy в SQL Server 2000 из-за длительной транзакции - PullRequest
6 голосов
/ 06 апреля 2011

Мы столкнулись с ситуацией на одном из наших производственных серверов. У нас есть особая процедура Store, которая выполняет операцию вставки одной из самых больших таблиц в БД (в ней более нескольких миллионов строк). Эта таблица является самой занятой таблицей в БД и имеет много зависимых от нее операций.

Недавно мы столкнулись с проблемой на одном конкретном производственном сервере.

Мы выполняем Insert SP вместе с некоторыми другими SP обновления в одной транзакции, и мы сталкиваемся с проблемой 'Долгосрочной транзакции' для Insert SP довольно регулярно. Всякий раз, когда мы сталкиваемся с этой проблемой, мы находим типичное поведение в данных, которые вставляются в таблицу. Значение столбца datetime вставляется как «ноль». Это происходит несколько раз для всех строк и некоторое время для нескольких строк. Значение datetime передается из приложения. Но другие операции обновления, которые выполняются до и после операции вставки, работают хорошо.

Мы запустили трассировку sql profiler в нашей тестовой среде (не на рабочем сервере), но обнаружили, что значение datetime каждый раз корректно передавалось.

Также, когда мы сталкиваемся с проблемой в производстве, мы наблюдаем, что:

  1. @@ trancount равен '0', но DBCC OPENTRAN отображает определенная открытая транзакция.
  2. Тип последнего ожидания имеет значение «NETWORKIO».
  3. Тип ожидания: «0x0000».
  4. Статус «спит».
  5. УРОВЕНЬ ИЗОЛЯЦИИ ЧИТАЕТСЯ НЕЗАВИСИМЫМ.

Итак, наша забота

  1. Почему дата-время вставляется как «NULL» только в этой конкретной ситуации?
  2. Как избежать этой ситуации, а также длительной транзакции?
  3. Что может быть причиной возникновения такой ситуации на одном конкретном сервере?

Заранее спасибо за помощь,

Abhijit

Ответы [ 3 ]

1 голос
/ 15 июня 2011

Звучит так, словно у тебя нехватка кода. Желательно изолировать ваши вставки, обновления и т. Д. В более мелкие транзакции.

Чтобы проверить, где происходит зависание, одну вещь, которую вы можете попробовать, - это просто добавить несколько этапов в вашу процедуру в виде печати («Сделано так далеко ...»). Затем выполните процедуру из SSMS и проверьте окно сообщений. Это отвратительный способ отладки, но если вы не хотите использовать меньшие транзакции или ловушку @@ error и т. Д., Это может быть вашим лучшим выбором.

1 голос
/ 15 июня 2011

«Мы выполняем вставку SP вместе с некоторыми другими обновлениями SP в одной транзакции»

Я бы порекомендовал разделить вашу вставку и обновления.Если вы знаете, что вам нужно сделать некоторые обновления после вставки, триггеры для обновлений могут быть правильным ответом.

Я также хотел бы предложить вам профиль для блокировки / блокировки.Я говорю это потому, что из того, что вы сказали, вы, вполне вероятно, будете использовать одни и те же строки более одного раза в своей корневой транзакции, основываясь на вероятной причине объединения всей этой активности в одном и том же процессе.

1 голос
/ 14 мая 2011

Есть несколько вещей, которые, я думаю, должны быть рассмотрены одновременно здесь.Во-первых, и это самое важное, я настоятельно рекомендую вам взглянуть на эту транзакцию, чтобы увидеть, что вы можете сделать, чтобы уменьшить нагрузку на вашу систему.Можно ли его разбить на несколько небольших транзакций?Поможет ли добавление лучших индексов?Будет ли захват подмножества данных и помещение их во временную таблицу уменьшать количество SELECTS, запускаемых по основной таблице?Список вопросов может продолжаться некоторое время.

Далее, посмотрите на «приложение», которое запускает транзакцию.Это проходит даты в?Если да, то как он это делает?Если он просто передает GetDate(), значит, SQL Server выполняет всю работу.Однако, если приложение передает значение даты, я бы удостоверился, что это значение даты ВСЕГДА допустимо.Если это так, посмотрите на таблицу, чтобы убедиться, что форматирование даты установлено правильно.Например, если ваше приложение было передано в европейском формате даты 14-05-2011, ваше приложение может подавиться, если оно ожидает месяц-день-год, поскольку 14 не конвертируется в месяц.

В-третьих, просмотритеваши таблицы, чтобы увидеть, если на них установлены какие-либо триггеры.Если вы это сделаете, посмотрите на каждый триггер очень внимательно.Вполне возможно, что триггер вызывает конфликт в вашей транзакции.Возможно, вы пишете данные, и ваш триггер возвращается и обновляет данные (или оценивает дату и говорит, что она недействительна - см. Пример выше).

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

Наконец, вам нужно взглянуть на свою тестовую среду.Если это работает в тесте, но не в производстве, между двумя системами есть что-то отличное.Это причина, прямо или косвенно.Может быть, это связано с аппаратным обеспечением (плохая оперативная память?) Или может быть что-то другое в настройках (блокировка, тот факт, что клиенты пытаются выполнить действия с данными и т. Д.)

Помимо этого, здесьссылка на форум с некоторыми другими потенциальными ответами для вас:

http://groups.google.com/group/comp.databases.ms-sqlserver/browse_thread/thread/1063b65df1f97492/8649bee2002646a2

...