Предотвратить тупик в совершенном чтении SELECT
Я извлекаю данные из бизнес-системы, предоставленной третьей стороной, для использования в отчетности. Я использую один оператор SELECT, выданный из компонента источника задачи потока данных служб SSIS, который объединяет несколько таблиц в исходной системе для создания нужного набора данных. Мы используем уровень изоляции по умолчанию для фиксации чтения.
К моему удивлению, я регулярно нахожу, что этот извлекающий запрос блокируется и выбирается в качестве жертвы. Я не думал, что SELECT в транзакции с фиксацией чтения мог бы сделать это, но в соответствии с этим ответом SO это возможно: может ли уровень изоляции с фиксацией чтения когда-либо приводить к тупику (Sql Server)?
С помощью флагов трассировки 1204 и 12222 я определил конфликтующее утверждение, а также объект и индекс, о которых идет речь. По сути, конкуренция происходит из-за страницы данных в первичном ключе одной из таблиц. Мне нужно извлечь из этой таблицы, используя соединение по ее ключу (поэтому я снимаю блокировку S), конфликтующий оператор выполняет INSERT и запрашивает блокировку IX на странице данных индекса.
(Примечание: вышеупомянутый SO говорит об этой проблеме, возникающей с некластеризованными индексами, но, похоже, это происходит в кластеризованном PK. По крайней мере, это то, во что я верю, основываясь на моей интерпретации информации о взаимоблокировке в журнале событий и свойство relatedObjectId.)
Вот мои ограничения:
- Конфликтующее заявление содержится в зашифрованной хранимой процедуре, предоставленной третьей стороной как часть готового программного обеспечения. Нет возможности получить открытый текст или изменить его.
- Я не хочу использовать "грязное чтение", так как мне нужны мои извлеченные данные для поддержания их целостности.
- Мне не ясно, как или если реструктуризация моего запроса извлечения может предотвратить это. Блокировка находится на ПК таблицы, которая меня больше всего интересует, и я не вижу альтернативы использованию ПК.
- Я не возражаю против того, чтобы мой запрос извлечения был жертвой, поскольку я предпочитаю это прерыванию оперативного использования исходной системы. Однако это приводит к сбою выполнения служб SSIS, поэтому, если это так, я бы хотел более четкий и изящный способ справиться с этой ситуацией.
Может кто-нибудь предложить способы, желательно, чтобы предотвратить тупик, или если нет, то лучше обработать ошибку?
1 ответ
Я предполагаю, что вы пытаетесь вставить в ту же таблицу, из которой вы выбираете. Если нет, то скриншот вкладки потока данных будет полезен при определении проблемы. Если да, то вам повезло - у меня была эта проблема раньше.
Добавьте сортировку в поток данных, так как это полностью блокирующее преобразование (см. Ниже о блокирующих преобразованиях). Это означает, что SELECT потребуется для завершения загрузки всех данных в буфер конвейера, прежде чем любые данные будут переданы в место назначения. В противном случае SSIS пытается вставить данные, когда есть блокировка таблицы / индекса. Вы можете быть в состоянии проявить творческий подход с вашими стратегиями индексации здесь (я не пробовал это). Но полностью блокирующее преобразование сделает свое дело и устранит необходимость в каких-либо дополнительных индексах для таблицы (и связанных с этим издержках).
Примечание: никогда не используйте подсказки запроса NOLOCK при выборе данных из таблицы, чтобы попытаться обойти это. Я никогда не пробовал этого и не собираюсь этого делать. Вы (королевский вы) рискуете вставить незафиксированные данные в ваш ETL.
Ссылка:
https://jorgklein.com/2008/02/28/ssis-non-blocking-semi-blocking-and-fully-blocking-components/