LATCH_EX ожидает ресурс METADATA_SEQUENCE_GENERATOR

11

У нас есть процесс, который генерирует отчет об инвентаризации. На стороне клиента процесс разбивает настраиваемое количество рабочих потоков для создания порции данных для отчета, которая соответствует одному хранилищу из многих (потенциально тысяч, обычно десятков). Каждый рабочий поток вызывает веб-сервис, который выполняет хранимую процедуру.

Процесс базы данных для обработки каждого чанка собирает кучу данных в таблицу #Teorary. В конце каждого блока обработки данные записываются в постоянную таблицу в базе данных tempdb. Наконец, в конце процесса один поток на стороне клиента запрашивает все данные из постоянной таблицы tempdb.

Чем больше пользователей запустят этот отчет, тем медленнее он будет. Я проанализировал активность в базе данных. В какой-то момент я увидел 35 отдельных запросов, все из которых были заблокированы в одной точке процесса. Все эти SPID имели порядка 50 мс ожидания типа LATCH_EXна ресурсе METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8). Один SPID имеет этот ресурс, а все остальные блокируют. Я не нашел ничего об этом ресурсе ожидания в веб-поиске.

Таблица в базе данных tempdb, которую мы используем, имеет IDENTITY(1,1)столбец. Ожидают ли эти SPID столбца IDENTITY? Какие методы мы могли бы использовать, чтобы уменьшить или устранить блокировку?

Сервер является частью кластера. Сервер работает под управлением 64-разрядной версии SQL Server 2012 Standard Edition с пакетом обновления 1 (SP1) в 64-разрядной версии Windows 2008 R2 Enterprise. Сервер имеет 64 ГБ ОЗУ и 48 процессоров, но база данных может использовать только 16, потому что это стандартная версия.

(Обратите внимание, что я не в восторге от использования постоянной таблицы в базе данных tempdb для хранения всех этих данных. Изменение этого было бы интересной технической и политической задачей, но я открыт для предложений.)

ОБНОВЛЕНИЕ 23.04.2013

Мы открыли дело о поддержке с Microsoft. Я буду держать этот вопрос в курсе, как мы узнаем больше.

ОБНОВЛЕНИЕ 5/10/2013

Инженер службы поддержки SQL Server согласился, что ожидания были вызваны столбцом IDENTITY. Снятие ИДЕНТИЧНОСТИ устранило ожидания. Мы не смогли продублировать проблему в SQL 2008 R2; это произошло только на SQL 2012.

Пол Уильямс
источник
Копирует ли процесс данные из таблиц #Teorary в постоянную таблицу или на этом шаге происходит дополнительная логика преобразования?
Джон Зигель
На этапе ожидания он копирует записи инвентаризации одного магазина в постоянную таблицу без преобразования. Мы могли бы работать внутри постоянной таблицы все время, но я думаю, что программист решил использовать временную таблицу # в качестве области хранения, чтобы предотвратить частое обновление данных для преобразования в блокировки PAGE.
Пол Уильямс

Ответы:

4

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

  1. Удалите IDENTITYсвойство из столбца в итоговой таблице.
  2. Создайте значения идентичности в каждой из таблиц #Teorary.
  3. При загрузке окончательной таблицы объедините числовой идентификатор для конкретного хранилища со значениями идентификаторов из шага 2.

Таким образом, если у вас есть идентификаторы хранилища 3 и 4, вы получите конечные значения идентификаторов, например:

3000000001
3000000002
3000000003
...
4000000001
4000000002
...

Или что-то похожее на это. Вы поняли идею.

Это исключит необходимость сериализации при IDENTITYгенерации при сохранении уникальности в конечном результате.

В качестве альтернативы, в зависимости от того, как работает процесс, вставьте окончательные рассчитанные значения идентификаторов в таблицы #Teorary. Тогда вы могли бы создать представление, которое UNION ALLобъединяет их, исключая необходимость вообще копировать данные.

Джон Сайгель
источник
Спасибо за ответ. Я согласен, если это проблема, использование какого-либо изготовленного ключа (или вообще никакого ключа) может исправить это. Мы открыли дело с Microsoft по этому вопросу. Я опубликую результаты здесь и приму ваш ответ, если они согласятся, что это проблема.
Пол Уильямс
@ Пол: Пожалуйста, дайте мне знать; Мне так же любопытно. Как и вы, я не смог найти в Интернете ничего об этой защелке, но вполне разумно, что это сериализация идентичности / последовательности. Трудно сказать, является ли это узким местом, хотя с более чем 30 потоками, конкурирующими за значения, это кажется вероятным. Вы также можете попробовать копировать из каждой таблицы #Teorary в серии (а не параллельно), чтобы посмотреть, поможет ли это.
Джон Зигель
2
Инженер SQL Server согласился, что это, вероятно, IDENTITYстолбец. Мы удалили его из уже широкого кластерного индекса и полностью удалили столбец. Это было не нужно. После этого эти ожидания LATCH_EX ушли. Мы не могли продублировать ожидания на SQL 2008 R2. Эта проблема возникла только в SQL Server 2012.
Пол Уильямс,
@Paul: Спасибо за продолжение. Очень интересно. Я предполагаю, что код, который генерирует IDENTITYзначения, был переписан для использования нового материала для генерации последовательности, который был новым в 2012 году. В <2012 вы можете увидеть другой тип защелки, хотя, если не было проблем с перфорированием, то, кажется, было регрессия в коде. В любом случае, удаление IDENTITYстолбца - самая безопасная вещь.
Джон Зигель
Вместо идентичности вы можете попытаться использовать «ПОСЛЕДОВАТЕЛЬНОСТЬ» (что является новым в SQL 2012)
Богдан Максим
7

(Обновлено в феврале 2019 г.)

Это старый пост, в котором говорится, что мне наконец удалось убедить Microsoft в том, что сам факт этого действительно является дефектом.

Обновление: MS подтвердил дефект и присвоил ему ошибку № 12628722.

Я видел этот пост в ноябре 2018 года, когда мы начали страдать примерно так же после того, как мы обновили Sql Server 2005 до Sql Server 2017. Таблица с 3,3 млн строк, которая раньше занимала 10 секунд для массовой вставки, внезапно начала занимать 10 минут на столах с Identityколоннами.

Оказывается, есть две проблемы:

  1. Microsoft изменила поведение в Sql Server 2014, чтобы заставить массовые вставки работать параллельно - в предыдущих версиях массовые вставки имели план сериализации.
  2. После параллельной работы нашего 32-ядерного блока двигатель провел больше времени, когда ядра блокировали друг друга, чем фактически выполнял работу.

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

Есть несколько возможных обходных путей, которые мы нашли, пока это не будет исправлено:

  1. Используйте Option (MaxDop 1)в запросе, чтобы превратить массовую вставку обратно в сериализованный план.
  2. Маскируйте столбец Идентичности, приводя его (например Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn)
    • это предотвращает копирование свойства идентификации при использовании SELECT...INTO
  3. Удалите столбец идентификаторов, как описано выше.
  4. Измените режим совместимости базы данных на Sql Server 2012 или ниже, чтобы заново установить сериализованный план.

Обновление: исправление, которое будет реализовывать MS, будет возвращать эти виды вставок обратно, используя Serialized план. Это запланировано для Sql Server 2017 CU14 (никаких новостей о других версиях Sql Server - извините!). При реализации Trace Flag 9492 необходимо будет включить либо на уровне сервера, либо через DBCC TraceOn .

Рейчел Эмблер
источник