Хочу поделиться опытом, касающимся распределенных баз. Ко мне обратился заказчик с просьбой восстановить обмен в распределенной базе, который перестал работать некоторое время назад. Беглый взгляд на монитор обмена привел меня в недоумение — откуда столько объектов для выгрузки (см. Рис. 1).
Помявшись, местный спец признался, что обмен из центральной базы в периферийную сломался два месяца назад, хотя в обратном направлении работает без проблем. На вопрос, почему тянули два месяца, внятного ответа я не получил. Размер файла обмена тем временем вырос до 3,7 Гб (несжатый).
Ладно. Симптомы отсутствия обмена — сообщение об ошибке (см. Рис. 2).
Причина, очевидно, «кривые» движения каких-либо документов.
Патрон (1С), в этом случае, советует перепроводить все документы, попавшие в выгрузку (см. Рис. 3).
Совет хороший, но был отметен сразу, как неосуществимый — слишком их много. Как локализовать источник ошибок?
Учитывая размер центральной базы (15 Гб) первым предположением было превышение суммарного размера одной или нескольких таблиц, величины в 4ГБ. Это не подтвердилось.
Тестирование и исправление ничего не дало. Выгрузка и повторная загрузка центральной и периферийной баз в dt не выявила каких-либо ошибок. Все проходило штатно. Обработка, которая ищет неуникальные комбинации (Регистратор, НомерСтроки) в движениях регистров не выявила ошибок. Код процедур проверки регистров приведен на Рис. 4.
Процедура КнопкаВыполнитьНажатие(Кнопка)
Ошибки.Очистить();
МетаданныеРегистрыНакопления = Метаданные.РегистрыНакопления;
КоличествоРегистров = МетаданныеРегистрыНакопления.Количество();
Для Сч = 1 По КоличествоРегистров Цикл
МетаданныеРегистр = МетаданныеРегистрыНакопления[Сч - 1];
ИмяРегистра = МетаданныеРегистр.Имя;
Если ИмяРегистра = "ПартииНоменклатуры" Тогда
//Продолжить;
КонецЕсли;
Сообщить(ИмяРегистра + " ???");
ТекстЗапроса = СформироватьТекстЗапросаПоРегистру(ИмяРегистра);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Сообщить(ИмяРегистра + " Okay");
Продолжить;
КонецЕсли;
Сообщить(ИмяРегистра + " + ");
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = Ошибки.Добавить();
НоваяСтрока.Регистратор = Выборка.Регистратор;
НоваяСтрока.Период = Выборка.Регистратор.Дата;
НоваяСтрока.ИмяРегистра = ИмяРегистра;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция СформироватьТекстЗапросаПоРегистру(ИмяРегистра)
ТекстЗапроса =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Данные.Регистратор КАК Регистратор
|ИЗ
| (ВЫБРАТЬ
| РегистрНакопления.Регистратор КАК Регистратор,
| РегистрНакопления.НомерСтроки КАК НомерСтроки,
| СУММА(1) КАК КоличествоДублей
| ИЗ
| РегистрНакопления." + ИмяРегистра + " КАК РегистрНакопления
|
| СГРУППИРОВАТЬ ПО
| РегистрНакопления.Регистратор,
| РегистрНакопления.НомерСтроки
|
| ИМЕЮЩИЕ
| СУММА(1) > 1) КАК Данные";
Возврат ТекстЗапроса;
КонецФункции
Кусочек кода, относящийся к регистру «Партии номенклатуры» появился, поскольку в файловом варианте попытка проверки приводила к аварийному закрытию сеанса с сообщением об ошибке «Недостаточно памяти» (32 Гб оперативной памяти — маловато, само собой).
Отключение итогов (кстати, аналогично, по совету патрона) тоже не помогло. Обе базы выглядели совершенно нормально. Ошибка возникала только при операции ПрочитатьИзменения() при загрузке файла. Возможно, это проблема платформы, как я сейчас думаю. Признаться, я зашел в тупик — предложение создать заново начальный образ периферийной базы я оставил в качестве последнего шанса не потерять лицо, да и не факт, что выгрузка прошла бы гладко.
Решение пришло внезапно. Кто сказал, что индексы должны быть уникальны? Далее, я создал базу SQL, загрузил туда периферийную базу, и начал попытки загрузить туда файл обмена. Как только загрузка вываливалась на ошибку (см. Рис. 5),
я снимал флажки уникальности с индексов таблиц регистров (Рис. 6).
Всего таких регистров нашлось шесть. Когда файл загрузился, я снова применил обработку поиска неуникальных комбинаций (Регистр, НомерСтроки), и получил таблицу «кривых» документов (см. Рис. 7).
После этого я сделал их непроведенными в центральной базе, выгрузил файл обмена, затем загрузил его в исходную периферийную. Все прошло нормально. Бинго!
PS. После этого я перепровел документы из таблицы и они ушли в периферийную без проблем.
Детектив с хэппиэндом 🙂 интересно, что скажет
начальник транспортного цехаместные гуру SQL(1) А какого рода комментариев вы от них ожидаете?
Можно было бы распровести документы в узле, загрузить файл обмена и провести непроведенные
Все правильно сделал. Сам через это проходил.
Аналогичная проблема была, когда пытались загрузить dt-шник в базу SQL. Ругалась на служебную таблицу, которую пришлось грохнуть, загрузив dt-шник сперва в Postgre, т.к. последний менее придирчив к уникальности индексов.
Простите, не понял, что нужно было распровести в узле? На картинке показано количество документов, которых не было в подчиненном узле. И они не могли туда попасть из-за ошибки чтения файла обмена.
Решение интересное. Пара вопросов. Если дубли были в базе источнике или в базе приемнике, то мы их должны были увидеть. Если дубли возникали при загрузке из-за неуникальности записей, то вариант предложенный в 3 должен был бы помочь — при перепроведении мы бы остановились бы на неуникальности. Или нет?
(6) Наверное, я в статье выразился недостаточно ясно, Обе базы, и центральная, и периферийная ошибок не содержали. Они прошли все тесты, которые мне пришли в голову:
а. Тестирование и исправление;
б. Выгрузку в dt и, последующую загрузку;
в. Выгрузку и последующую загрузку в SQL;
с. Поиск запросом в регистрах накопления неуникальных пар Регистратор,Номер строки.
Ошибка возникала в момент загрузки файла обмена, не раньше и не позже. Загружаемых документов, вместе с их движениями, в периферийной базе не было.
Поэтому мне совсем непонятна отсылка на совет (3). Что я должен был распровести и провести обратно в подчиненном узле? Все документы за несколько лет работы? А в главном — пять тысяч с гаком? Представляете время, которое бы это заняло? И не факт, что это удалось бы. Проще тогда заново создать начальный образ. Меня остановило только то, что не было уверенности, что созданная база будет валидна с точки зрения обмена РИБ, ведь работают те же механизмы.
После того, как я нашел эти документы, они перепровелись без проблем. И пропутешествовали в периферийную тоже без проблем. Т.е. кривизна в движениях регистров была таки, но такая, которая не «ловится» средствами 1С и появляется стохастически. Вот почему я грешу на платформу. .
Автор ничего не упомянул о версии платформы и MSSQL. А это, на мой взгляд, очень важно.
Вообще РИБ меняются данными с минимумом программного кода (или вообще без), все действия в чтении и записи 1с выполняет сама. И то, что появилась такая ошибка, наводит на мысль об ошибке в платформе. Было бы интересно, если бы автор выложил трассировку ошибки и более глубоко разобрал причины. Но в любом случае идея хорошая.
А еще можно было бы вообще отключить проблемный индекс ) А потом его перестроить.
Очень странно, что ошибка вообще возникла, да еще на этом индексе. Вангую, что обычная запись набора записей без проблем выполнилась бы. Гранулярность обмена для РН — регистратор… Откуда бы взяться ошибке?
(8) Честно говоря, я не подумал, что версии платформы и MSSQL могут иметь значение. Ну раз это важно, версия платформы, в которой была создана база SQL — 8.2.19.106. Версия MSSQL — 2005.090.5000.00. Если этого недостаточно, то прилагается скриншот с полными данными по MSSQL. При тестировании в файловом режиме ошибка возникала на платформах 8.2.19.130, 8.3.8.2137, 8.3.9.2033. Так что мой вывод — ошибка не зависит от релиза платформы. Если это ошибка платформы, то она тянется, наверное, еще со времен 8.1. Мне думается, что сама 1С считает механизм РИБ устаревшим, поэтому ничего в нем не меняет.
По поводу минимума программного кода, вы абсолютно правы. В сущности все сводится к методам ЗаписатьИзменения и ПрочитатьИзменения. С отладчиком не сунешься, увы.
По поводу трассировки: что вы имеете в виду?
(9)
Других механизмов то же не предлагает….
В БСП исправляют ошибки связанные с обменами в РИБе.
А так ошибок уже каких только не встречал в РИБах. Из последнего на лету без остановки рег заданий заменили правила регистрации. РИБ так лаганул что в узлы попали документы из других узлов. А некоторые документы замножились. И вместо одно документа получили 10 одинаковых документов с одним и тем же номером в узле и ЦБ.
Были проблемы с движениями. Были проблемы с обменами когда падало из за какого то глючного объекта.
(10) Мне кажется, что тренд — Конвертация данных, вот уже второе поколение пошло…
Ну а куда от РИБа уйдёшь?
Конечно может есть способы… Интересно было бы посмотреть. Пока что всё что видел было по сути тем же РИБом в доп костылями.
(12) Трудно спорить. На мой взгляд, единственное преимущество конвертации — возможность поковыряться отладчиком в случае чего.