<?php // Полная загрузка сервисных книжек, создан 2026-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
Оригинальная идея.
Оригинально !
Интересно! Достали уже тормоза стандартного журнала…
красота
Скорость — это не единственное что можно извлечь.
По данному регистру можно делать запросы, что позволяет:
— отслеживать ошибки — если пользователи молчат как рыбы
— составлять статистику интенсивности работы пользователей
— можно реализовать отчет по времени проведения документов (т.к. в данных фиксируется время начала и окончания транзакции)
— …
А чем отличается от ?
(6) отличия следующие:
0) представленная разработка является копией штатного журнала регистрации, но только хранится в базе и соответственно позволяет быстро считывать данные
1) не снижает производительность при записи объектов
2) корректно показывает в т.ч. отмененные транзакции
3) позволяет отследить длительность этих самых транзакций
4) не показывает изменение реквизитов
(6) По всей видимости тем, что здесь используется стандартный журнал регистрации, просто загруженный в регистр сведений (т.е. в нем кроме изменений в данных еще куча информации: ошибки, сеансы и.т.д).
А то что по ссылке работает на подписках на события и ловит только изменения данных:
«Дополнительный журнал регистрации предназначен для быстрого получения данных о фактах изменения объектов базы данных.»
посмотри в последней УПП версионность
но ведь на справочнике быстрее будет работать чем в регистре…
не пойму зачем разрешать системному механизму каждый раз при записи делать проверку уникальности регистра сведений.. её ж никак неотключить
а на справочнике — пожалуйста..
(10) сам придумал или кто подсказал? проверка выполняется при вставке индекса на стороне SQL сервера
по тестам (гдето на мисте была статья даже)
запись около 10000 эл в справочник vs Рег Сведений
Справочник соотв. без автонумерации и контроля
пишет в 2 раза быстрее в среднем 🙂
вот так то
думаю самый быстрый вариант будет через ole доступ к sql-серверу
+ создание дополнительной базы и сохранение только guidов или ключей ссылки (что даже предпочтительнее, ищется быстрее чем по МД)
(12) Результаты теста:
Запись справочника 1 : 0сек.
Запись регистра 1 : 0сек.
Запись справочника 10 : 0сек.
Запись регистра 10 : 0сек.
Запись справочника 100 : 0сек.
Запись регистра 100 : 0сек.
Запись справочника 1 000 : 4сек.
Запись регистра 1 000 : 0сек.
Запись справочника 10 000 : 37сек.
Запись регистра 10 000 : 2сек.
вот так то
хы) ну значит ацкие прогеры с мисты опять накосячили
а я им верил…
А как это скажется на размере базы с большим количеством пользователей, за продолжительное время? Примерные цифры есть?
есть, но это уже за отдельную плату.
механизм используется на большом количестве баз с числом активных пользователей до 100, так же работает на центральной базе для РИБ из ~15узлов.
правда для больших баз пришлось изменить структуру индексов в SQL
Сам недавно об этом думал .. и именно такую реализацию прикидывал…
Ну наверно об возможности безболезненного удаления объектов из ИБ можно забыть 🙂
(18) Если у в конфе есть журналы, то конечно их нужно игнорить при проверке ссылок на объект перед удалением.
(19) представленный механизм учитывает необходимость удаления объектов, при этом записи в журнале и ссылки на объекты в этих записях остаются.
(14) Цитата :
«Запись справочника 10 000 : 37сек.
Запись регистра 10 000 : 2сек.»
Правильно ли я понял описание теста ?
Рассматривается клиент-серверный вариант 1сПредприятия 8.
Цикл с количеством итераций 10 000 , добавляющий записи в справочник, имеет продолжительность — 37 сек
Для регистра сведений с аналогичной структурой процедура формирования набора записей 10 000 шт. для регистра с аналогичной структурой
и единственная запись набора занимает — 2 сек.
(21)да
в представленном механизме, записи делаются не по одной, а пачкой
(22) Такая реализация предполагает при эффективности записи возможность потери изменений . Так ?
(23) нет. потери данных журнала не происходит ни при каких обстоятельствах
(24) …Предполагаю , что необходимо смотреть текст , чтобы убедиться в этом.
Здесь неоднократно поднимался вопрос «регистр или справочник ?»
И хотя , несомненно что :
1. Одна запись в справочник добавляется значительно быстрее чем в регистр.
2. При записи в справочник отсутствуют «тормозящие» блокировки , в отличие
от записи в регистр.
Тем не менее , Вы выбрали в качестве объекта хранения данных Регистр сведений с записью «пачками» и с «тормозящими» блокировками.
Возможно , в данной конкретной задаче у Вас были какие-то основания для этого ?
Чем так привлекателен оказался для Вас — регистр сведений ?
Извиняюсь , нужно уходить . До вечера.
(25) регистр — быстрее значительно если пачкой. тест я уже привел
(27)
Вопросов нет. Есть замечание .
Вставка описания теста в сообщение (14) —
1. сделала бы ненужной фразу «вот так-то »
2. и пост не сбил бы с толку (15)
странно в том что в версии ЖР от Бизнес-Плюс сделано таки на справочнике…
мне кажется тут надо провести диагностику скорости записей на разных базах, от 1 пользователя до 100 и более.
и скорее всего до какого то момента выгоднее использовать справочник
хотя отдельное спасибо за фри версию) жаль не могу плюс поставить
рейта не хватает 🙁
Прикольная штука, только одно небольшое замечание.
Если уж делаешь сделал для своего ЖР Роли, то негоже использовать в коде конструкции:
Показать полностью
Потому что, если не успел задать пользователю новую роль из подсистемы, то попытка посмотреть регистра журнала приводит к вылету приложения.
Всё-таки в этом случае нужно использовать Запрос, с ключевым словом РАЗРЕШЕННЫЕ
(28) Методика теста повторяет используемую в решении логику.
(29) Представленное решение ВООБЩЕ не снижает производительность системы. В регистр пишутся данные в режиме оффлайн, в отличие от механизмов Бизнес-Плюса.
(30) А не надо лазить куда не надо.
Супер. Очень даже ничего, вот еще бы штатно во всех конфах подобное было.
В нашей конфе присутствует подобное решение около года, т.е. все изменения документов и справочников регистрируются в регистре свидений. В результате накопилось более 2 млн. записей — при этом при открытии списка записей происходит висяк, даже если нужно посмотреть историю изменения с отбором по документу — открывается достаточно долго…
(33) всего 2 миллиона? это мало
я считаю такой способ хранения лога источником лишних блокировок и раздувания размера базы. Как результат — снижение производительности в целом.
(34) подрезали переодически. а так в день до более 20 тыс. записий было
1) блокировки — в предложенном решении их нет по определению. В других решениях — в зависимости от реализации
2) размер базы — ну да, данные хранятся в базе и увеличивают ее размер. с этим ничего поделать нельзя. Можно конечно хранить данные не в объектах 1С, а непосредственно в базе и обращаться прямыми запросами — но тогда интерфейсная часть будет более сложной и может притормаживать.
3) общее снижение производительности из-за роста базы — бред. наличие в базе большой таблицы, не влечет за собой снижения производительности. Также правильно организованная структура данных (и алгоритмов работы с этими данными) позволяет добиться стабильно высокой производительности вне зависимости от размеров таблицы.
(36) а мы не подрезаем 🙂
почему же нет блокировок — запись в данный регистр это уже блокировка, насколько я знаю и увеличение времени проведения документа.
(41) В моем решении дополнительных блокировок нет в принципе. Увеличения времени записи / проведения документов нет в принципе.
и к тому же, если обычный просмотр записей с отбором по измерениям этого регистра грузит проц и забивает память — это уже мешает остальным пользователям работать.
(41) анализ данных за большой период без отборов может нагрузить систему на несколько секунд. но я не вижу ситуации, когда это надо. Даже если выполняется статистический анализ с использованием запросов — это весегда дополнительные условия, и если правильно писать запросы — это несколько секунд.
(40) В какой момент тогда у тебя происходит запись в регистр
(43) запись в регистр происходит в отдельном фоновом задании.
(44) т.е. это делается в отдельное время или во время работы юзеров ?
и данные получается собираются из стандартного журнала ?
(45) в описании написано:
… является копией штатного журнала регистрации …
Автору спасибо. Третий месяц работы подсистемы в живой базе. Сколько раз выручала.
Есть ли возможность программной записи в данный журнал регистрации без регистрации в системном журнале регистрации, т.е. аналог штатного метода ЗаписьЖурналаРегистрации ?
Т.е. не хочется дублировать данные в 2-х журналах, а сразу писать в быстрый журнал.
нет, это противоречит идеологии решения — в регистре хранится копия данных
Общий вопрос о выборе объекта хранения изменений.
Если в качестве объекта хранения изменений использовать справочник с единственным реквизитом Дата и табличной частью по структуре аналогичной регистру сведений , то тогда добавление «пачки» строк не будет приводить к перезаписи всей табличной части элемента справочника .
И такая операция будет осуществляться значительно быстрее , чем запись «пачки» в регистр сведений.
С Вашей точки зрения , оправдан ли такой подход ?
Велики ли дополнительные издержки , с ним связанные ?
(50) а попробывать?
и есть подводный камень — как удалять объекты, на которые есть ссылки в журнале? при использовании регистра это проблема решается — в автоматическом режиме и при этом данные из регистра не удаляются.
(51) Ок.Подумаю.
Схема работы понравилась, ввел в свои рабочие базы.
Вопросы:
1. каким образом можно вести работу в базах на РБД?
2. есть ли опыт ввода подобной системы для РБД, например, для контроля работы удаленных пользователей?
(53) ни на одном проекте пока не требовался перенос данных журнала в ЦБД
однако при необходимости можно подумать, но за некоторое вознаграждение…
(51) Нет. Не стоит.
Если скорость записи «пачки» в регистр удовлетворительна , то идея замены регистра на справочник и создания дополнительного функционала становится неразумной.
(0) Похоже, что нарисовалось неудобство использования подсистемы после нескольких месяцев использования при большем объеме РС.
При добавлении в базу новых объектов (справочник, документов) идет очень долгая реструктуризация всех записей РС 🙁
ИМХО это происходит, потому что у 3-го измерения стоит тип условия ЛюбаяСсылка.
А ведь добавление новых объектов в рабочую базу происходит не так и редко.
Что можно сделать?
(56) Обрезать регистр. Ну мы вот сейчас остановились на обрезании по глубине времени. Для журнальных регистров для каждого задаем свою глубину хранения по времени. Можно еще сделать по количеству записей конечно, но это менее предсказуемо.
Взял идею данной подсистемы и воплотил в нашей системе.
Заметил одну неприятную штуку —
8.1.15.14
Установлено разделение хранения журнала регистрации «день» и уровень «Ошибки, Предупреждения»
Периодически выполняется выгрузка кодом
Фильтр = Новый Структура;
Фильтр.Вставить(«ДатаОкончания», ТекущаяДата());
Фильтр.Вставить(«ДатаНачала», ДатаАктуальности + 1);
ИмяФайлаДанных = ПолучитьИмяВременногоФайла(«xml»);
ВыгрузитьЖурналРегистрации(ИмяФайлаДанных, Фильтр);
Стал замечать, что на границах суток журнал перестает выгружаться. Похоже пока не откроешь системную форму журнала регистрации, метод ВыгрузитьЖурналРегистрации почему то возвращает пустой файл. Как только я открываю системную форму журнала (главное меню, сервис, Журнал регистрации), все сразу само начинает работать (создается ожидаемый файл выгрузки).
В описании не совсем точно написано «Будет работать только на клиент-серверном варианте базы». Hаботает и в файл-серверном, но с ручным обновлением/запуском регламентного задания.
1. Каким образом можно быстро очистить сабжевый регистр сведений?
Штатный способ — создать набор записей и тут же его записать — работает очень медленно (за полгода набрали 14 млн записей).
Или хотя бы убрать самую старую часть данных, т.е. ограничение по времени.
2. Кстати, а почему измерения регистра, кроме DateRef, не индексируются?
Например, поле Date вообще не индексировано, в результате отборы по периодам также могут подтормаживать.
(60) 1 — или так, или напрямую в SQL.
2. ну поле Date индексируется по определению, оно вообще первое в кластерном индексе, индекс по номеру записи вообще не имеет смысла, а по DataRef индекс есть. но вообще на больших таблицах есть смысл перестроить индексы напрямую в SQL — убрать все составные индексы и сделать только по нужным полям. Это позволит значительно сократить объем индексов
(61) Скрипт по индексам не подскажешь? я лично подобное на 8.1 еще не делал 🙁
(62) нахаляву — только типовой вариант, а оптимизация — за отдельную плату.
Интересно, а как будет работать данная разработка при полном перепроведении базы в монопольном режиме (Перепроведение мес занимает 12 часов) 🙂
Регламентное задание отработает после снятия мнопольного режима и повиснит на чтении XML файла. В тоже время, даже, если XML файл будет прочтен, далее повиснит на записи в регистр, т.к. будет записываться огромный кусок информации.
(64) нормально будет работать
нигде ничего не зависнет
(0) А на 8.2 эта штука заработает? Может я что-то конечно не так сделал, но у меня в консоли регламентных заданий обработка загрузки завершилась с ошибкой:
ОбщийМодуль.жр_ЖурналРегистрации.Модуль(205)}: Поле объекта не обнаружено (EventName).
Стал искать журнальчик для себя, среди прочих, и по крайней мере из того, что пока удалось найти, Ваш лидирует по качеству исполнения и кода, а еще вообще сама идея хорошая. Я бы еще добавил для себя вот такое , и тогда было бы вообще все просто зашибись. Однако у меня оно на 8.2 так и не заработало 😥
Люди-и-и, хоть у кого-нибудь эта штука на 8.2 работает а? Или все на 8.1 сидят?
(68) У меня заработало, недавно перевел конфу на 8.1 и решил проблему неверной работы.
(69) Поздно, я уже себе переписал 🙂
Интересная разработка.
У меня 8,2
При сравнении и объединении конфигураций, база перестала работать….
т.е. она загружается но ни один документ, справочник не работает.
хм…