![]() |
![]() |
|
Возможно проблема кэширования 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
|
Попробовал выполнять запрос в транзакции, проблему не решило, но стала проявляться новая ситуация:
После закрытия смены, робот пытается выгрузить данные первый раз есть проблема со сменой, а например во второй раз (времени проходит меньше минуты) уже нет, но так происходит в некоторых случаях, до этого такого замечено не было. Возможно выполнение запроса в транзакции все-таки оказывает какое-то влияние на кэш или я раньше по какой-то причине не замечал такого поведения, хотя это вряд ли. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |