Имя: Пароль:
1C
 
Возможно проблема кэширования 1с
0 parcan
 
28.04.09
16:17
Поднимал уже такую тему на infostart.ru попробую и тут.
.
С ЧЕГО НАЧАЛАСЬ ТЕМА
.
Попытаюсь понятно сформулировать свою ситуацию:
Общее:
На точках стоит программа написанная на 1с (написана мною, код знаю как свои 5 пальцев). Продавец запускает программу (это один процесс) в которой осуществляет продажи. Первый процесс при старте запускает второй (фоновый) процесс 1с, который периодически отправляет данные с точки в офис и подгружает данные из офиса. Используется файловый вариант работы 1с. На точках используются 2 релиза платформы 8.1.12.98 и 8.1.13.37. Все действия производимые обоими процессами программы подробно пишутся в лог-файлы и логи соответственно присылаются ко мне.
Существует документ смена, который создается пустой (заполнены только номер и дата) при открытии смены в магазине. Вечером продавец делает закрытие смены и этот документ перезаписывается с заполненными данными. Далее фоновый процесс отправляет данные этого документа в офис. Каждый объект имеет реквизит статус типа перечисления в котором хранится текущий статус объекта (не выгружен, выгружен в офис, загружен в офисе, отклонен в офисе) фоновый процесс ориентируется по этим статусам что ему делать.
Проблема:
Периодически на различных точках фоновый процесс при выгрузке документа как будто получает старую версию документа в которой еще не заполнены данные.
Попытаюсь провести объяснение последовательности происходящих событий по своему логу с пояснениями:
.
Утром продавец открывает смену, записан документ смена с заполненными датой и номером, все остальные реквизиты пустые.
22.04.2009 8:37:51 kassir Открыта смена : Смена 16 от 22.04.2009 8:37:51
.
Вечером продавец закрывает смену, перезаписан документ с заполненными параметрами, тут привожу только ДатаЗакрытия.
22.04.2009 22:33:47 kassir (до записи объекта) Документ объект: Смена Номер: 16 Дата: 22.04.2009 8:37:51 ДатаЗакрытия: 22.04.2009 22:33:47
22.04.2009 22:33:47 kassir Закрыта смена : Смена 16 от 22.04.2009 8:37:51
22.04.2009 22:33:47 kassir (после записи объекта) Документ объект: Смена Номер: 16 Дата: 22.04.2009 8:37:51 ДатаЗакрытия: 22.04.2009 22:33:47
.
Далее робот (фоновый процесс) выполняет запрос документов смена в которых реквизит ДатаЗакрытия <> Дата(1,1,1) и по полученным ссылкам выгружает данные.
22.04.2009 22:33:49 robot (при выгрузке) Документ ссылка: Смена Номер: 16 Дата: 22.04.2009 8:37:51 ДатаЗакрытия: 01.01.0001 0:00:00
Получается, что при выполнении запроса у документа смена реквизит ДатаЗакрытия заполнен, а вот в полученной ссылке из запроса этот реквизит уже не заполнен (как впрочем и все остальные).
При выгрузке документа фоновый процесс robot вновь перезаписывает документ меняя ему статус на выгружен. В итоге оказывается записан документ со статусом выгружен, но с пустыми реквизитами.
.
Далее может оказаться еще интереснее. Продавец печатает отчет за последнюю смену. Через МенеджерДокументов получаем ссылку на последний документ и выводим его данные
22.04.2009 22:34:00 kassir Напечатана строка: ДАТА ОТКР.: 22.04.2009 08:37:51
22.04.2009 22:34:00 kassir Напечатана строка: ДАТА ЗАКР.: 22.04.2009 22:33:47
Получается, что у продавца в документе данные все еще заполнены, но так бывает редко, обычно после робота и у продавца документ уже тоже имеет пустые данные.
.
В результате после всего этого в базе остался документ с незаполненными реквизитами.
Закономерности этой проблемы выявить не смог, может несколько дней на всех точках работать все нормально, а потом на некоторых происходить такой косяк.
При перезаписи объекта стал использовать Получить() ничего не изменилось.
Код промониторил вдоль и поперек все выполняется четко.
Операции выводимые в лог длятся меньше секунды, т.е. их последовательность точно не нарушена.
.
Единственное оставшееся у меня предположение, что это как то связано с кэшированием данных либо самой 1с либо системы в целом.
.
ЧЕМ ЗАКОНЧИЛАСЬ ТЕМА
.
После обсуждения был еще более детализирован лог и добавлена подписка на событие ПриЗаписи() для документа Смена.
.
В итоге событие ПриЗаписи() никогда не отрабатывает лишний раз и нет никакого обнуления документа Смена.
.
Но интересен лог для следующего кода в фоновом процессе робота
//*********************************************
Процедура ОбработатьПродажи(ТолькоНовые=Истина)
 
  МассивСтатусов = Новый Массив;
  МассивСтатусов.Добавить(Перечисления.СтатусыФайловогоОбмена.ПустаяСсылка());
  МассивСтатусов.Добавить(Перечисления.СтатусыФайловогоОбмена.Создан);
  Если Не ТолькоНовые Тогда   //выгруженные
     МассивСтатусов.Добавить(Перечисления.СтатусыФайловогоОбмена.Выгружен);
  КонецЕсли;
 
  Запрос = Новый Запрос("ВЫБРАТЬ
                        |   Смена.Ссылка КАК Ссылка
                        |ИЗ
                        |   Документ.Смена КАК Смена
                        |ГДЕ
                        |   Смена.ДатаЗакрытия <> &ПустаяДата
                        |   И Смена.Статус В(&СтатусыФайловогоОбмена)
                        |УПОРЯДОЧИТЬ ПО
                        |   Смена.Дата"
                        |;
                        |
                        |//////////////////////////////////////////////////­//////////////////////////////
                        |ВЫБРАТЬ
                        |   Чек.Ссылка КАК Ссылка
                        |ИЗ
                        |   Документ.Чек КАК Чек
                        |ГДЕ
                        |   Чек.Статус В(&СтатусыФайловогоОбмена)
                        |
                        |УПОРЯДОЧИТЬ ПО
                        |   Чек.Дата
                        |;
                        |
                        |//////////////////////////////////////////////////­//////////////////////////////
                        |ВЫБРАТЬ
                        |   ВнесениеИзъятие.Ссылка КАК Ссылка
                        |ИЗ
                        |   Документ.ВнесениеИзъятие КАК ВнесениеИзъятие
                        |ГДЕ
                        |   ВнесениеИзъятие.Статус В(&СтатусыФайловогоОбмена)
                        |
                        |УПОРЯДОЧИТЬ ПО
                        |   ВнесениеИзъятие.Дата");
  Запрос.УстановитьПараметр("ПустаяДата", Дата(1,1,1));
  Запрос.УстановитьПараметр("СтатусыФайловогоОбмена", МассивСтатусов);
 
  МассивРезультатов = Запрос.ВыполнитьПакет();
  МассивСмен = МассивРезультатов[0].Выгрузить().ВыгрузитьКолонку("Ссылка");
  МассивЧеков = МассивРезультатов[1].Выгрузить().ВыгрузитьКолонку("Ссылка");
  МассивВнесенийИзъятий = МассивРезультатов[2].Выгрузить().ВыгрузитьКолонку("Ссылка");
 
  Для Каждого Смена Из МассивСмен Цикл
     _Временный._ВывестиВЛогДанныеСмены(Смена, "(результат запроса робота)");
  КонецЦикла;
 
  СформироватьПродажи(МассивСмен, МассивЧеков, МассивВнесенийИзъятий);
 
КонецПроцедуры // ОбработатьПродажи()
//*********************************************
.
В _Временный._ВывестиВЛогДанныеСмены(ОбъектИлиСсылка, Описание) происходит только запись в лог-файл и ничего более.
.
Данные из лог-файла:
27.04.2009 22:31:02 robot (результат запроса робота) Документ ссылка: Смена Номер: 2 Дата: 27.04.2009 7:59:56 ДатаЗакрытия: 01.01.0001 0:00:00
.
При выполнении запроса ДатаЗакрытия заполнена сразу после выполнения запроса ДатаЗакрытия пустая. Никаких изменений объекта Смена в это время не происходит, т.е. подписка на событие ПриЗаписи() не отрабатывает (в подписке на событие для логирования тоже вызываеться _Временный._ВывестиВЛогДанныеСмены(Источник, "(подписка на событие)"))
.
По всему набору имеющихся лог-файлов с проблемами выяснил что от времени выполнения запроса в процессе робота и сохранения смены в процессе продавца это не зависит, т.е. разница во времени составляла от 0 секунд до почти 4х минут во всем промежутке этого времени косяк может произойти, а может не произойти.
На данный момент вероятность появления косяка варьируется в пределах 0-20%.
.
в общем волшебство :)
1 ТелепатБот
 
гуру
28.04.09
16:17
2 parcan
 
28.04.09
17:23
up
3 parcan
 
28.04.09
20:04
никаких предположений?
4 yukon
 
28.04.09
20:28
(0) >На точках используются 2 релиза платформы 8.1.12.98 и 8.1.13.37

Учитывая что стабильные релизы это 8.1.12.101 и 8.1.13.41 проблема может быть, как минимум, трояка:
1. Глючит один из нестабильных релизов
2. Глючат оба нестабильных релиза
3. Глючит работа системы в разных релизах
5 parcan
 
29.04.09
10:54
(4) возможно, но на сайте 1с в изменениях к обоим этим стабильным релизам ничего даже даже отдаленно похожего на мою проблему в исправлениях не значиться.
6 hhhh
 
29.04.09
11:02
(5) так ты же не посылал эту ошибку в 1С. Вот она и не значится в исправлениях.
7 Advan
 
29.04.09
11:05
Пиши доки на выгрузку в отдельный список после проведения или регистрируй в плане обмена.
8 Advan
 
29.04.09
11:08
у тебя неправильная архитектура обмена - не зря все используют отдельные таблицы регистрации.
9 parcan
 
29.04.09
11:36
как отдельная таблица регистрации решит проблему того что в фоновом процессе считываеться старая версия объекта? Напишу я в отдельную таблицу ссылку для выгрузки, фоновый робот возьмет эту ссылку и по ней получит старые данные.

я через задницу проблему обошел и следующим постом опишу результат, я теперь уже на 99.9% уверено что есть проблема с кешем 1с.
10 parcan
 
29.04.09
11:55
Переписал конец выложенной процедуры следующим образом (сделал постпроверку смены и если проверку не проходит, то пропускать эту смену)

   МассивСменПроверенный = Новый Массив;
   Для Каждого Смена Из МассивСмен Цикл
       _Временный._ВывестиВЛогДанныеСмены(Смена, "(результат запроса робота)");
       Если ЗначениеЗаполнено(Смена.ДатаЗакрытия) Тогда
           МассивСменПроверенный.Добавить(Смена);
       КонецЕсли;
   КонецЦикла;
   
   //СформироватьПродажи(МассивСмен, МассивЧеков, МассивВнесенийИзъятий);
   СформироватьПродажи(МассивСменПроверенный, МассивЧеков, МассивВнесенийИзъятий);

Получилось некрасиво но зато очень показательно.

Результат на всех точках смены закрылись.
Основная масса точек не круглосуточная и вечером выключают компьютер, есть несколько круглосуточных точек, на которых компьютер выключают только если проблемы со светом.
И мне повезло эта байда произошла на одной из круглосуточных точек, в результате я вижу что смена там закрылась, открылась новая, но фоновый процесс робота уже 2 часа не может мне прислать эту закрытую смену, т.е. 2 часа в запросе данные заполнены в полученной ссылке данные не заполнены и прислать мне эту смену программа смогла только после перезагрузки, вдруг волшебным образом данные в запросе и в полученной ссылке в фоновом процессе робота оказались одинаковыми.

Мы тут помозговали кэширование есть наверняка и на уровне самой 1с и на уровне операционной системы (используется файловый вариант базы данных).
кеширование на уровне 1с: т.е. выполнение запроса и считывание данных по ссылке производиться разными способами и один из них использует кэш а второй либо не использует либо использует как-то по другому.
кеширование на уровне операционной системы: замечено 2 или 3 случая когда по логам запись в базу записана, потом даже отправлена в офис, далее скачек напряжения, комп перегружаеться в базе записи как небывало.

Посмотрел в сторону ms sql server так там при возникновении проблем с кэшем можно воспользоваться спецкомандой и все никакого кеша ты 100% получаешь верные результат соответствующий БД, может и в 1с есть какая недокументированная функция или как то попытаться донести до разработчиков эту проблему, тока как они ее вопроизведут я ее 2 недели по логам отслеживал и вычислял
11 parcan
 
29.04.09
12:11
(6) а как обратиться в 1с я по сайт полазил, очень интуитивно непонятный интерфейс у них, может расскажете как к ним можно обратиться и что для этого надо сделать
12 parcan
 
29.04.09
15:58
есть еще какие мысли?
13 hhhh
 
29.04.09
16:16
(11) я уже давно обращался, года 3 назад, сейчас и не вспомню. Но сто процентов они попросят базу выслать с ошибкой, так что придется еще тестовую базу ваять, где эта ошибка проявляется.
14 parcan
 
29.04.09
16:57
(13) да я вышлю безпроблем тока у них моя прога не заработает, она сертификатом к нашему серверу привязана :(
15 parcan
 
29.04.09
18:15
С партнерской конференции
Адининский Александр (Хьюмен Систем, Минск)
Есть 2 компоненты одного программного решения - серверная и клиентская части. При их работе выявилась такая проблема (по этапам):

1) Клиентская часть выполняет соединение с базой через COMConnector.
(VB)
Set COMConnector = CreateObject("V8.COMConnector")
Set COMConnect = COMConnector.Connect(ConString)

2) Клиентская часть получает представление элемента справочника
ExtRefPresentation = COMConnect.String(ExtRef)

3) Серверная часть через COM-соединение выполняет изменение элемента справочника (изменяет наименование).

4) Клиентская часть пытается получить представление и получает СТАРОЕ значение. Новое представление удается получить, только выполнив подключение через COM еще раз.

Это ошибка платформы? Если нет, то почему так может происходить, если да - как обойти эту проблему?

Виктор Сосновский (1С, Москва)
Если клиентская часть удерживает объект "СправочникОбъект" на переменной ExtRef, то обновление элемента справочника серверной частью вносит изменение в запись базы данных, но не может внести изменение в объект "СправочникОбъект", который удерживается на переменной ExtRef клиентской частью. Чтобы изменения в базе данных отразились в объекте необходимо выполнить метод "Прочитать" этого объекта или получить новый объект "СправочникОбъект".

Адининский Александр (Хьюмен Систем, Минск)
Во избежание описанных проблем и клиентская и серверная части используют ссылки на объекты 1С. Захват самого объекта происходит _только_ при изменении данных.
Для получения представления захват объекта, естественно, не нужен, соответственно ExtRef - ссылка.

Виктор Сосновский (1С, Москва)
Если ExtRef - ссылка, то получение ее представления выполняется через кеш представлений, который в описанной ситуации может содержать устаревшие данные. При необходимости получения гарантированно актуальных данных необходимо получение данных выполнять в транзакции.

Адининский Александр (Хьюмен Систем, Минск)
При каких условиях или через какой интервал времени кэш представлений обновляется? И касается ли эта ситуация ТОЛЬКО представления объекта, или любых его данных (если я вдруг захочу получить не представление, а наименование например).
16 parcan
 
29.04.09
18:19
С другого форума

Радченко пишет, что в транзакционном кэше все данные считаются валидными, и после фиксации транзакции транзакционный кэш очищается. еще можно попробовать при получении ссылки на док блокировать эти данные, тогда скорее всего произойдет проверка валидности данных в обычном кэше. 1с размещает кэш в оперативной памяти.
17 parcan
 
29.04.09
18:24
Попробовать в запросе использовать конструкцию "ДЛЯ ИЗМЕНЕНИЯ" Блокировать получаемые данные для последующего изменения?
18 parcan
 
29.04.09
20:06
На других форумах пришли к мысли, что запрос надо выполнять в транзакции, чтобы система проверила данные из кэша на валидность.
19 parcan
 
05.05.09
13:38
Попробовал выполнять запрос в транзакции, проблему не решило, но стала проявляться новая ситуация:
После закрытия смены, робот пытается выгрузить данные первый раз есть проблема со сменой, а например во второй раз (времени проходит меньше минуты) уже нет, но так происходит в некоторых случаях, до этого такого замечено не было.
Возможно выполнение запроса в транзакции все-таки оказывает какое-то влияние на кэш или я раньше по какой-то причине не замечал такого поведения, хотя это вряд ли.
Компьютеры — прекрасное средство для решения проблем, которых до их появления не было.