Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 SSIS обработка ошибок  [new]
IDVT
Member

Откуда:
Сообщений: 320
Добрый день, подскажите пожалуйста, больше спрашивать не у кого...

Есть ETL пакет, который трансформирует и актуализирует данные ХД из промежуточной области (StageDB). Таблицы промежуточной области заполняет дочерний пакет, по факту родительский пакет параллельно запускает N'ое количество дочерних пакетов (количество указывается в параметрах родителя), при этом все шаги получения данных дочернего объекта обернуты в цикл, на тот случай если параметр количества параллельной обработки имеет меньшее значение чем количество источников данных. Все пакеты имеют обработчик событий OnError, который пишет (обычный insert с параметрами) в таблицу логирования.
Вопрос:
В Visual Studio все работает отлично, если у одного из экземпляров дочернего пакета в каком-то источнике данных возникает исключение (сервер недоступен, БД в монопольном режиме…) то обработчик событий фиксирует ошибку и переходит в цикле к следующему источнику. Все прям так, как и хотел. Но развернутый пакет в службу Integration Services ведет себя совсем по-другому, в случае выявленного исключения дочернего пакета фиксирует ошибку в таблицу логирования и просто заворачивает родительский пакет. Причину пока не удается выявить, отчеты SSIS нечего внятного не показывают, обработчик событий не фиксирует исключения в таблицу именно такой ситуации.

Вызов дочернего пакета в родителе осуществляет компонент Script, есть одна особенность, развернутый родительский пакет в службе Integ.Services так же обращается к локальному файлу дочернего пакета, но я сомневаюсь что тут причина.

+
           string DTSXPackage = Dts.Variables["$Package::Local_DTSXPackageDirectory"].Value.ToString()
                               + Dts.Variables["$Package::Local_DTSXPackageNameFor1C"].Value.ToString();           // путь + имя дочернего пакета 
            var TasksFlow = new List<Thread>();                                                               // список задач
            Int32 CountRunFlow = Convert.ToInt32(Dts.Variables["$Package::CountFlows"].Value);                // количество потоков
            Int32 NumRepetition = Convert.ToInt32(Dts.Variables["User::NumRepetition"].Value);                // номер итерации цикла повторной попытки загрузки данных
            Boolean ExceptionFlow = false;                                                                    // признак наличия хотябы одного исключения, в дочерних пакетах



            DataTable DTableList = new DataTable();
            DTableList.Columns.Add("NumGroupFlow", typeof(int));
            DTableList.Columns.Add("CFDid", typeof(string));
            DTableList.Columns.Add("LinkedName", typeof(string));
            DTableList.Columns.Add("DBName", typeof(string));
            DTableList.Columns.Add("DateLoad", typeof(DateTime));

            OleDbDataAdapter OLDBA = new OleDbDataAdapter();
            System.Data.DataTable DTable = new System.Data.DataTable();
            OLDBA.Fill(DTable, Dts.Variables["User::SourceDataList"].Value);

            foreach (DataRow row in DTable.Rows)
            {
                object[] array = row.ItemArray;
                DTableList.Rows.Add(new object[] { Convert.ToInt32( array[0].ToString())      // (NumGroupFlow) номер группы потока
                                                 , array[1].ToString()                        // (CFDId)        код ЦФО
                                                 , array[2].ToString()                        // (LinkedName)   наименование связанного сервера
                                                 , array[3].ToString()                        // (DBName)       наименование БД источника
                                                 , Convert.ToDateTime(array[4].ToString())    // (DateGP)       дата ГП
                                                  });
            }

            // от кривых рук, защита от дурака (кол. потоков не может быть меньше 1 и привышать количество источников данных*)
            // источник данных - таблица, содержащая перечень параметров (линк, имя БД, дата ГП,..) по всем ЦФО
            if (CountRunFlow < 1)
            {
                CountRunFlow = 1;
            }
            if (CountRunFlow > DTable.Rows.Count)
            {
                CountRunFlow = DTable.Rows.Count;
            }

            // формирование задач потоков

            for (int i = 0; i < CountRunFlow; i++)
            {
                int NumFlowsExecute = i + 1;                                   // текущий номер потока
                var Thread = new Thread(() => RunPackage( NumFlowsExecute      // номер группы для потока
                                                        , NumRepetition        // номер итерации цикла повторной загрузки данных ЦФО, в каторых выявлено исключение
                                                        , DTableList           // список параметров (переменных) по всем ЦФО
                                                        , DTSXPackage          // путь к дочернему пакету
                                                        , ref ExceptionFlow));
                Thread.Start();
                TasksFlow.Add(Thread);
            }

            // проверка на завершение потоков

            while (TasksFlow.Any(t => t.ThreadState == System.Threading.ThreadState.Running))
            {
                Thread.Sleep(1000);
            };

            Dts.Variables["User::ExceptionFlow"].Value = ExceptionFlow;

            Dts.TaskResult = (int)ScriptResults.Success;

        }
        static void RunPackage(int NumFlowsExecute, int NumRepetition, object SourceDataList, string DTSXPackage, ref Boolean ExceptionFlow)
        {
            Application app = new Application();
            Package pkg = app.LoadPackage(DTSXPackage, null);
            Variables vars = pkg.Variables;
            vars["User::NumFlowsExecute"].Value = NumFlowsExecute;
            vars["User::SourceDataList"].Value = SourceDataList;
            vars["User::NumRepetition"].Value = NumRepetition;
            pkg.Execute(null, vars, null, null, null);

            if (pkg.ExecutionResult.ToString() == "Failure")
            {
                ExceptionFlow = true;
            }
        }
        #region ScriptResults declaration

        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion

    }


В обоих случаях, что в Visual Studio, что на сервере родительский пакет после выявленного исключения дочернего(их) пакета(ов), благополучно переходит к следующему этапу на котором в цикле повторно пытается извлечь данные из источника с определенным количеством попыток и временем ожидания между итерациями цикла. Повторюсь: Если повторная загрузка данных пакета, развернутого на сервере, терпит не удачу (исключение), то родительский пакет прерывает свое выполнение, без фиксации исключения.
4 апр 17, 09:06    [20363566]     Ответить | Цитировать Сообщить модератору
 Re: SSIS обработка ошибок  [new]
IDVT
Member

Откуда:
Сообщений: 320
Visual Studio 2015
сервер
Microsoft SQL Server 2016 (SP1-CU2) (KB4013106) - 13.0.4422.0 (X64)   Mar  6 2017 14:18:16   Copyright (c) Microsoft Corporation  Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor) 
4 апр 17, 09:09    [20363574]     Ответить | Цитировать Сообщить модератору
 Re: SSIS обработка ошибок  [new]
SQL2008
Member

Откуда: Москва
Сообщений: 4540
IDVT, попробуйте изменить параметр (не помню как называется точно) "кол-во ошибок, после которого пакет завершает работу".
По умолчанию установлена 1.
4 апр 17, 12:10    [20364637]     Ответить | Цитировать Сообщить модератору
 Re: SSIS обработка ошибок  [new]
IDVT
Member

Откуда:
Сообщений: 320
SQL2008
IDVT, попробуйте изменить параметр (не помню как называется точно) "кол-во ошибок, после которого пакет завершает работу".
По умолчанию установлена 1.
в том то и дело, изначально в дочернем пакете задал значение этого параметра = 0, немного собрал информации от админов, в те дни когда когда SSIS ведет себя неадекватно, у одного из филиалов не было электричества, но если электричество есть а БД по прежнему недоступна (по каким то причинам), пакет отрабатывает должным образом. Не понимаю в чем закономерность... какая разница сервер включен или нет, я же обращаюсь к нему по линку, достучался все хорошо, не достучался - перехожу к следующему источнику. Мистика какая то =)
4 апр 17, 12:17    [20364683]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить