SQL 2016 SQL Server Утверждение: Файл: <pageref.cpp>, строка = 951 Неудачное утверждение

8

В настоящее время я обновляю наше хранилище данных с SQL 2012 до SQL 2016. У меня есть как старый, так и новый DW, работающие параллельно.

Мой процесс ETL (среда, разработанная в службах SSIS сторонней организацией) успешно выполняется более 2 лет в 2012 году, но не работает в 2016 году. Пока базы данных и процесс ETL идентичны.

Оба Сервера являются Виртуальными машинами, работающими на VMWare. Старый сервер - это Win 2008 с 24 ГБ оперативной памяти. SQL 2012 Std. Max mem установлен на 16Gb. Новый сервер - Win 2012 с 64 ГБ оперативной памяти. SQL 2016 dev. Max mem установлен на 50Gb. Новый DW работает под управлением версии 13.0.1601.5 RTM Developer Edition (64-разрядная версия).

Во время выполнения моего ETL-процесса шаги загрузки, использующие SQL-слияние в таблицу измерений или фактов, завершаются неудачно со следующей ошибкой.

Полный текст:

ОПИСАНИЕ: SQL Server Утверждение: File:, line = 951 Failed Assertion = 'IS_OFF (BUF_MINLOGGED, m_buf-> bstat) || pageModifyType! = PageModifyType_Contents || GetPagePtr () -> IsTextPage () '. Эта ошибка может быть связана с синхронизацией. Если ошибка повторяется после повторного выполнения оператора, используйте DBCC CHECKDB, чтобы проверить целостность базы данных, или перезапустите сервер, чтобы убедиться, что структуры данных в памяти не повреждены.

В соответствии с рекомендациями я запустил DBCC, и ошибок не было найдено. Я также перезапустил SQL. Затем я перезапустил процесс ETL и получил ту же ошибку.

Мои поиски этой ошибки показывают, что это известная ошибка в SQL 2008, 2012 и 2014 и исправленная в последующих исправлениях и накопительных обновлениях. поэтому я немного удивлен, увидев его в 2016 году.

Ссылки, которые я нашел, говорят, что это влияет на SSIS при попытке выполнить вставку, если база данных находится в модели восстановления Simple или Bulk Logged. (Я работаю в простой модели восстановления)

Предлагаемый обходной путь - изменить модель восстановления Db на FULL. Я пробовал это, и это работает, но это не так уж много решений для хранилища данных.

Кто-нибудь еще сталкивался с этим с 2016 года?

Кто-нибудь может предложить альтернативные обходные пути?

Обновления:

26/7/2016: я применил критическое обновление KB3164398 (v13.0.1708.0), и проблема все еще существует.

27.07.2016: Я применил накопительное обновление CU1 KB3164674 (v13.0.2149.0).

08.03.2016: Ошибка произошла быстро на нашем самом маленьком кубе. CU1 не решил проблему. Сегодня я сообщил об ошибке в MS Connect. Я также записал в службу поддержки Microsoft.

8/12/2016: MS-Support ответила изначально, но ответ был «У нас нет решения для этого». Парень из службы поддержки собирался обсудить это со своими коллегами и вернуться ко мне. 8 дней спустя я ничего не слышал от него.

Хотя у меня нет «исправления», мы нашли способ, который нас устроил. Смотрите мой ответ.

29/9/2016. Я применил CU2 на прошлой неделе. В четверг мы случайно запустили старую версию слияния, которая снова провалилась с той же ошибкой. Так что .. CU2 тоже не починил.

23/1/2017 : Я применил 2016 SP1 CU1 и считаю, что это решило проблему. Конкретно KB3205964

Сэр ругается много
источник

Ответы:

2

Глядя на КБ, у вас есть несколько вариантов / обходных путей:

  1. Переключиться на полную модель восстановления. Вы говорите: «Это не слишком вариант для склада», но на самом деле это просто вопрос регулярного создания резервных копий журнала транзакций, например, 15 минут, а затем их утилизации. В SSIS / планы технического обслуживания есть стандартные задачи для этого . Вы потеряете транзакции с массовой регистрацией, но я никогда не обнаруживал, что они сильно повлияли на время выполнения, только на размер журнала. Вы можете даже сделать резервную копию журнала в NUL, который я не буду описывать здесь. Если вы не уверены, что делать, обратитесь к местному администратору базы данных. Сохранение резервной копии дискового пространства и журнала транзакций - это более простые проблемы, чем фатальные ошибки. Когда эта проблема в конце концов будет решена, вы можете переключиться обратно.
  2. В КБ упоминается «несколько операторов BULK INSERT в одной распределенной транзакции». Из вашего вопроса не ясно, как настроены ваши массовые вставки. Используете ли вы SSIS для запуска задач «Выполнение SQL», которые используютMERGEкоманда? Что здесь означает «несколько BULK INSERT»? Есть ли способ преобразовать ваш подход в отдельные BULK INSERT, например, по одному за раз? Например, в SSIS вы можете временно установить для MaxConcurrentExecutables значение 1, посмотрите, поможет ли это. Свяжите его с переменной config, чтобы вы могли изменить его позже. Очевидно, это замедлит ход событий, но вы предпочитаете, чтобы ваш ETL заканчивался, а не быстро проваливался. Параллельное выполнение операций - это хорошая модель и реальная сила SSIS, но вы можете работать только так быстро, как ваш самый медленный компонент; скажем, у вас есть 10 измерений, которые занимают минуту, и один факт, который занимает час, ваш ETL заканчивается через час, параллельный или 1 час 10 минут, работающий последовательно.
  3. MERGEэто хорошо, но есть несколько проблем. Вы могли бы рассмотреть возможность преобразования обратно в INSERT/ UPDATE. Также вы должны использовать HOLDLOCKс MERGEсогласно здесь . Вы используете этот намек? Есть ли какая-то разница в этом вопросе, если вы делаете? У нас была проблема в ранней сборке SQL 2014, когда использование MERGEс компонуемым DML ( OUTPUTпредложение) в columnstore вызвало такое утверждение - я заставил их убрать индексы columnstore из измерений, которые они добавили, не сказав мне.
  4. Какую обработку транзакций вы делаете? Иногда с ETL позиция повторяется путем повторного запуска. Иногда вам нужно, чтобы он потерпел неудачу и откат. Как вы это реализовали? Может быть изменено, чтобы это не «единая распределенная транзакция»?

Удачи.

wBob
источник
Привет @wBob спасибо за ваш ответ. Чтобы ответить на ваши вопросы. 1. Мы говорим о извлечении таблиц 20-30Gb за один шаг. перемещение более 100 ГБ данных. Я беспокоюсь о том, чтобы выбросить логи TX, а также хранилище. Может быть, я мог бы сделать резервную копию журнала шаг в ETL после каждого извлечения? 2. Да, SSIS вызывает задачу SQL для выполнения слияния. Каждый шаг выполняется последовательно. В то время, когда выполняется слияние, это единственная выполняемая задача. 3. Наш инструмент ETL является платформой, предоставляемой поставщиком. Вот как это работает. Не уверен насчет подсказок. проверю. 4. Нет обработки TX. Прямой SQL.
Сэр Клятва-много-много
Так что, если успешные запуски не продолжаются, попробуйте 100 ГБ t-log с резервными копиями журналов после каждого перемещения таблицы, что должно его отсортировать. Очевидно, вы должны проверить. Какие-либо другие особенности, которые мы должны знать о цели? Columnstore, разбиение, чрезмерная индексация?
wBob
В настоящее время нет функций, которых нет в нашей существующей версии DW на 2012 год. Новые DW / Datamarts являются точной копией оригиналов, без хранилищ столбцов или разделов. Минимальные (но эффективные) показатели. В настоящее время мы фокусируемся на переходе платформы на подобие. В конечном итоге, наша новая версия DW будет 2016 Enterprise. Но мы не добавим функции уровня предприятия, пока не начнем работать с основами.
Сэр Клянется
Привет @ wBob. Мы вроде как реализовали ваше предложение, вырвав вставку из слияния. Но, учитывая то, как я задал вопрос, я не уверен, что считается правильным ответом. но я думаю, что вы привели меня к действительному и эффективному обходному пути.
Сэр, клянется много
2

Я считаю, что это было решено в 2016 году SP1 CU1.

В частности, по KB3205964

Сэр ругается много
источник
1

Это исправлено путем применения накопительного обновления 1 (CU1) для MSSQL2016, см. Ссылку https://support.microsoft.com/en-us/kb/3164674.

Стив Нешаузен
источник
Стив работал со мной над этим. мы думали, что решили, но без сигары. поэтому я убрал кредит и понизил рейтинг.
Сэр, клянется много
1

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

Мы изменили часть вставки оператора слияния, чтобы она вставлялась во временную таблицу, а не в исходную цель.

Как только оператор слияния выполняется, мы вставляем из #table в цель.

Это не идеально, но, по крайней мере, объединение все еще обрабатывает сложность 'upsert', отмечая строки, которые были удалены / истекли.

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

CREATE TABLE #Activity(
[ETL_ActivitySurrogateKey] [int] IDENTITY(1,1) NOT NULL,
[Field1] [varchar](255) NULL,
)

-- Insert statements for procedure here
INSERT INTO #Activity ( [Field1],2,3,etc )

SELECT [Field1],2,3,etc
FROM 
(
    MERGE [DDS_OZ_CC].[dimActivity] AS target 
    USING (
      SELECT [Field1],2,3,etc
      FROM [STAGE_OZ_CC].[Transform_Activity]
      ) as source
    ON
    (
      target.RowIsCurrent = source.RowIsCurrent
         AND target.[Field1] = source.[Field1]
    )
    WHEN MATCHED 
        AND (        
        EXISTS (SELECT target.Level5Id EXCEPT SELECT source.Level5Id)
    )
    THEN
      UPDATE SET 
        ETL_ValidToDateTime = source.ETL_ValidFromDateTime 
       ,ETL_RowIsCurrent = 0 
       ,ETL_LastTouchedBy = source.ETL_LastTouchedBy 
       ,ETL_RowChangeReason = 'SCD2 Retired' 

    WHEN NOT MATCHED THEN 
    INSERT 
    (    
     [Field1],2,3,etc
    )
    VALUES (      
      source.[Field1],2,3,etc
    )
       WHEN NOT MATCHED BY SOURCE AND target.ETL_RowIsCurrent = 1
       THEN UPDATE SET
       ETL_RowIsCurrent = 0 
       ,ETL_RowChangeReason = 'Fact Removed' 
       ,ETL_LastTouchedBy = 'Unknown'

  OUTPUT
    $action      
      ,source.[Field1],2,3,etc    

  ) AS MergeOutput
  (
    action  
    ,[Field1],2,3,etc   
  ) 

  WHERE ACTION = 'UPDATE' AND ETL_RowIsCurrent = 1

    INSERT INTO [DDS_OZ_CC].[dimActivity]
    ( [Field1],2,3,etc  )
    SELECT [Field1],2,3,etc
    FROM #Activity

    END
Сэр ругается много
источник
Хорошо, спасибо, Питер. Просто из интереса, вы пробовали подсказку HOLDLOCK?
wBob
Нет, я не После прочтения статьи Аарона Бертранса я понял, что на самом деле речь идет о проблемах параллелизма с несколькими пользователями. В нашем случае выполняется только процесс ETL.
Сэр, клянется много
Я думаю, что стоило попытаться просто посмотреть, если у вас другое поведение, плюс это, вероятно, лучшая практика, просто сказать, что вы не согласны сейчас, не значит, что вы не можете быть в будущем. Во всяком случае, молодцы, нашли решение и
приступили
Я бы хотел, но, к сожалению, у нас нехватка времени. Как только мы нашли работоспособное решение, босс призвал двигаться дальше.
Сэр, клянется много