Быстрый журнал регистрации




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?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='\

73 Comments

  1. Gamm

    Оригинальная идея.

    Reply
  2. cs25

    Оригинально !

    Reply
  3. Magister

    Интересно! Достали уже тормоза стандартного журнала…

    Reply
  4. spidem

    красота

    Reply
  5. Expert1C

    Скорость — это не единственное что можно извлечь.

    По данному регистру можно делать запросы, что позволяет:

    — отслеживать ошибки — если пользователи молчат как рыбы

    — составлять статистику интенсивности работы пользователей

    — можно реализовать отчет по времени проведения документов (т.к. в данных фиксируется время начала и окончания транзакции)

    — …

    Reply
  6. noblekey

    А чем отличается от http://infostart.ru/projects/2529/ ?

    Reply
  7. Expert1C

    (6) отличия следующие:

    0) представленная разработка является копией штатного журнала регистрации, но только хранится в базе и соответственно позволяет быстро считывать данные

    1) не снижает производительность при записи объектов

    2) корректно показывает в т.ч. отмененные транзакции

    3) позволяет отследить длительность этих самых транзакций

    4) не показывает изменение реквизитов

    Reply
  8. Valet

    (6) По всей видимости тем, что здесь используется стандартный журнал регистрации, просто загруженный в регистр сведений (т.е. в нем кроме изменений в данных еще куча информации: ошибки, сеансы и.т.д).

    А то что по ссылке работает на подписках на события и ловит только изменения данных:

    «Дополнительный журнал регистрации предназначен для быстрого получения данных о фактах изменения объектов базы данных.»

    Reply
  9. Кадош

    посмотри в последней УПП версионность

    Reply
  10. inse0f

    но ведь на справочнике быстрее будет работать чем в регистре…

    не пойму зачем разрешать системному механизму каждый раз при записи делать проверку уникальности регистра сведений.. её ж никак неотключить

    а на справочнике — пожалуйста..

    Reply
  11. Expert1C

    (10) сам придумал или кто подсказал? проверка выполняется при вставке индекса на стороне SQL сервера

    Reply
  12. inse0f

    по тестам (гдето на мисте была статья даже)

    запись около 10000 эл в справочник vs Рег Сведений

    Справочник соотв. без автонумерации и контроля

    пишет в 2 раза быстрее в среднем 🙂

    вот так то

    Reply
  13. inse0f

    думаю самый быстрый вариант будет через ole доступ к sql-серверу

    + создание дополнительной базы и сохранение только guidов или ключей ссылки (что даже предпочтительнее, ищется быстрее чем по МД)

    Reply
  14. Expert1C

    (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сек.

    вот так то

    Reply
  15. inse0f

    хы) ну значит ацкие прогеры с мисты опять накосячили

    а я им верил…

    Reply
  16. artmicro

    А как это скажется на размере базы с большим количеством пользователей, за продолжительное время? Примерные цифры есть?

    Reply
  17. Expert1C

    есть, но это уже за отдельную плату.

    механизм используется на большом количестве баз с числом активных пользователей до 100, так же работает на центральной базе для РИБ из ~15узлов.

    правда для больших баз пришлось изменить структуру индексов в SQL

    Reply
  18. German

    Сам недавно об этом думал .. и именно такую реализацию прикидывал…

    Ну наверно об возможности безболезненного удаления объектов из ИБ можно забыть 🙂

    Reply
  19. tormozit

    (18) Если у в конфе есть журналы, то конечно их нужно игнорить при проверке ссылок на объект перед удалением.

    Reply
  20. Expert1C

    (19) представленный механизм учитывает необходимость удаления объектов, при этом записи в журнале и ссылки на объекты в этих записях остаются.

    Reply
  21. Ish_2

    (14) Цитата :

    «Запись справочника 10 000 : 37сек.

    Запись регистра 10 000 : 2сек.»

    Правильно ли я понял описание теста ?

    Рассматривается клиент-серверный вариант 1сПредприятия 8.

    Цикл с количеством итераций 10 000 , добавляющий записи в справочник, имеет продолжительность — 37 сек

    Для регистра сведений с аналогичной структурой процедура формирования набора записей 10 000 шт. для регистра с аналогичной структурой

    и единственная запись набора занимает — 2 сек.

    Reply
  22. Expert1C

    (21)да

    в представленном механизме, записи делаются не по одной, а пачкой

    Reply
  23. Ish_2

    (22) Такая реализация предполагает при эффективности записи возможность потери изменений . Так ?

    Reply
  24. Expert1C

    (23) нет. потери данных журнала не происходит ни при каких обстоятельствах

    Reply
  25. Ish_2

    (24) …Предполагаю , что необходимо смотреть текст , чтобы убедиться в этом.

    Здесь неоднократно поднимался вопрос «регистр или справочник ?»

    И хотя , несомненно что :

    1. Одна запись в справочник добавляется значительно быстрее чем в регистр.

    2. При записи в справочник отсутствуют «тормозящие» блокировки , в отличие

    от записи в регистр.

    Тем не менее , Вы выбрали в качестве объекта хранения данных Регистр сведений с записью «пачками» и с «тормозящими» блокировками.

    Возможно , в данной конкретной задаче у Вас были какие-то основания для этого ?

    Чем так привлекателен оказался для Вас — регистр сведений ?

    Reply
  26. Ish_2

    Извиняюсь , нужно уходить . До вечера.

    Reply
  27. Expert1C

    (25) регистр — быстрее значительно если пачкой. тест я уже привел

    Reply
  28. Ish_2

    (27)

    Вопросов нет. Есть замечание .

    Вставка описания теста в сообщение (14) —

    1. сделала бы ненужной фразу «вот так-то »

    2. и пост не сбил бы с толку (15)

    Reply
  29. inse0f

    странно в том что в версии ЖР от Бизнес-Плюс сделано таки на справочнике…

    мне кажется тут надо провести диагностику скорости записей на разных базах, от 1 пользователя до 100 и более.

    и скорее всего до какого то момента выгоднее использовать справочник

    хотя отдельное спасибо за фри версию) жаль не могу плюс поставить

    рейта не хватает 🙁

    Reply
  30. Sol

    Прикольная штука, только одно небольшое замечание.

    Если уж делаешь сделал для своего ЖР Роли, то негоже использовать в коде конструкции:

    Код
    ПриложениеСсылка = Справочники.жр_Приложения.НайтиПоКоду(Код);
    

    Показать полностью

    Потому что, если не успел задать пользователю новую роль из подсистемы, то попытка посмотреть регистра журнала приводит к вылету приложения.

    Всё-таки в этом случае нужно использовать Запрос, с ключевым словом РАЗРЕШЕННЫЕ

    Reply
  31. Expert1C

    (28) Методика теста повторяет используемую в решении логику.

    (29) Представленное решение ВООБЩЕ не снижает производительность системы. В регистр пишутся данные в режиме оффлайн, в отличие от механизмов Бизнес-Плюса.

    (30) А не надо лазить куда не надо.

    Reply
  32. wirg

    Супер. Очень даже ничего, вот еще бы штатно во всех конфах подобное было.

    Reply
  33. StasN

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

    Reply
  34. Expert1C

    (33) всего 2 миллиона? это мало

    Reply
  35. StasN

    я считаю такой способ хранения лога источником лишних блокировок и раздувания размера базы. Как результат — снижение производительности в целом.

    Reply
  36. StasN

    (34) подрезали переодически. а так в день до более 20 тыс. записий было

    Reply
  37. Expert1C

    1) блокировки — в предложенном решении их нет по определению. В других решениях — в зависимости от реализации

    2) размер базы — ну да, данные хранятся в базе и увеличивают ее размер. с этим ничего поделать нельзя. Можно конечно хранить данные не в объектах 1С, а непосредственно в базе и обращаться прямыми запросами — но тогда интерфейсная часть будет более сложной и может притормаживать.

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

    Reply
  38. Expert1C

    (36) а мы не подрезаем 🙂

    Reply
  39. StasN

    почему же нет блокировок — запись в данный регистр это уже блокировка, насколько я знаю и увеличение времени проведения документа.

    Reply
  40. Expert1C

    (41) В моем решении дополнительных блокировок нет в принципе. Увеличения времени записи / проведения документов нет в принципе.

    Reply
  41. StasN

    и к тому же, если обычный просмотр записей с отбором по измерениям этого регистра грузит проц и забивает память — это уже мешает остальным пользователям работать.

    Reply
  42. Expert1C

    (41) анализ данных за большой период без отборов может нагрузить систему на несколько секунд. но я не вижу ситуации, когда это надо. Даже если выполняется статистический анализ с использованием запросов — это весегда дополнительные условия, и если правильно писать запросы — это несколько секунд.

    Reply
  43. StasN

    (40) В какой момент тогда у тебя происходит запись в регистр

    Reply
  44. Expert1C

    (43) запись в регистр происходит в отдельном фоновом задании.

    Reply
  45. StasN

    (44) т.е. это делается в отдельное время или во время работы юзеров ?

    и данные получается собираются из стандартного журнала ?

    Reply
  46. Expert1C

    (45) в описании написано:

    … является копией штатного журнала регистрации …

    Reply
  47. Поручик

    Автору спасибо. Третий месяц работы подсистемы в живой базе. Сколько раз выручала.

    Reply
  48. artbear

    Есть ли возможность программной записи в данный журнал регистрации без регистрации в системном журнале регистрации, т.е. аналог штатного метода ЗаписьЖурналаРегистрации ?

    Т.е. не хочется дублировать данные в 2-х журналах, а сразу писать в быстрый журнал.

    Reply
  49. Expert1C

    нет, это противоречит идеологии решения — в регистре хранится копия данных

    Reply
  50. Ish_2

    Общий вопрос о выборе объекта хранения изменений.

    Если в качестве объекта хранения изменений использовать справочник с единственным реквизитом Дата и табличной частью по структуре аналогичной регистру сведений , то тогда добавление «пачки» строк не будет приводить к перезаписи всей табличной части элемента справочника .

    И такая операция будет осуществляться значительно быстрее , чем запись «пачки» в регистр сведений.

    С Вашей точки зрения , оправдан ли такой подход ?

    Велики ли дополнительные издержки , с ним связанные ?

    Reply
  51. Expert1C

    (50) а попробывать?

    и есть подводный камень — как удалять объекты, на которые есть ссылки в журнале? при использовании регистра это проблема решается — в автоматическом режиме и при этом данные из регистра не удаляются.

    Reply
  52. Ish_2

    (51) Ок.Подумаю.

    Reply
  53. artbear

    Схема работы понравилась, ввел в свои рабочие базы.

    Вопросы:

    1. каким образом можно вести работу в базах на РБД?

    2. есть ли опыт ввода подобной системы для РБД, например, для контроля работы удаленных пользователей?

    Reply
  54. Expert1C

    (53) ни на одном проекте пока не требовался перенос данных журнала в ЦБД

    однако при необходимости можно подумать, но за некоторое вознаграждение…

    Reply
  55. Ish_2

    (51) Нет. Не стоит.

    Если скорость записи «пачки» в регистр удовлетворительна , то идея замены регистра на справочник и создания дополнительного функционала становится неразумной.

    Reply
  56. artbear

    (0) Похоже, что нарисовалось неудобство использования подсистемы после нескольких месяцев использования при большем объеме РС.

    При добавлении в базу новых объектов (справочник, документов) идет очень долгая реструктуризация всех записей РС 🙁

    ИМХО это происходит, потому что у 3-го измерения стоит тип условия ЛюбаяСсылка.

    А ведь добавление новых объектов в рабочую базу происходит не так и редко.

    Что можно сделать?

    Reply
  57. tormozit

    (56) Обрезать регистр. Ну мы вот сейчас остановились на обрезании по глубине времени. Для журнальных регистров для каждого задаем свою глубину хранения по времени. Можно еще сделать по количеству записей конечно, но это менее предсказуемо.

    Reply
  58. tormozit

    Взял идею данной подсистемы и воплотил в нашей системе.

    Заметил одну неприятную штуку —

    8.1.15.14

    Установлено разделение хранения журнала регистрации «день» и уровень «Ошибки, Предупреждения»

    Периодически выполняется выгрузка кодом

    Фильтр = Новый Структура;

    Фильтр.Вставить(«ДатаОкончания», ТекущаяДата());

    Фильтр.Вставить(«ДатаНачала», ДатаАктуальности + 1);

    ИмяФайлаДанных = ПолучитьИмяВременногоФайла(«xml»);

    ВыгрузитьЖурналРегистрации(ИмяФайлаДанных, Фильтр);

    Стал замечать, что на границах суток журнал перестает выгружаться. Похоже пока не откроешь системную форму журнала регистрации, метод ВыгрузитьЖурналРегистрации почему то возвращает пустой файл. Как только я открываю системную форму журнала (главное меню, сервис, Журнал регистрации), все сразу само начинает работать (создается ожидаемый файл выгрузки).

    Reply
  59. tormozit

    В описании не совсем точно написано «Будет работать только на клиент-серверном варианте базы». Hаботает и в файл-серверном, но с ручным обновлением/запуском регламентного задания.

    Reply
  60. artbear

    1. Каким образом можно быстро очистить сабжевый регистр сведений?

    Штатный способ — создать набор записей и тут же его записать — работает очень медленно (за полгода набрали 14 млн записей).

    Или хотя бы убрать самую старую часть данных, т.е. ограничение по времени.

    2. Кстати, а почему измерения регистра, кроме DateRef, не индексируются?

    Например, поле Date вообще не индексировано, в результате отборы по периодам также могут подтормаживать.

    Reply
  61. Expert1C

    (60) 1 — или так, или напрямую в SQL.

    2. ну поле Date индексируется по определению, оно вообще первое в кластерном индексе, индекс по номеру записи вообще не имеет смысла, а по DataRef индекс есть. но вообще на больших таблицах есть смысл перестроить индексы напрямую в SQL — убрать все составные индексы и сделать только по нужным полям. Это позволит значительно сократить объем индексов

    Reply
  62. artbear

    (61) Скрипт по индексам не подскажешь? я лично подобное на 8.1 еще не делал 🙁

    Reply
  63. Expert1C

    (62) нахаляву — только типовой вариант, а оптимизация — за отдельную плату.

    Reply
  64. oscar2002

    Интересно, а как будет работать данная разработка при полном перепроведении базы в монопольном режиме (Перепроведение мес занимает 12 часов) 🙂

    Регламентное задание отработает после снятия мнопольного режима и повиснит на чтении XML файла. В тоже время, даже, если XML файл будет прочтен, далее повиснит на записи в регистр, т.к. будет записываться огромный кусок информации.

    Reply
  65. Expert1C

    (64) нормально будет работать

    нигде ничего не зависнет

    Reply
  66. sound

    (0) А на 8.2 эта штука заработает? Может я что-то конечно не так сделал, но у меня в консоли регламентных заданий обработка загрузки завершилась с ошибкой:

    ОбщийМодуль.жр_ЖурналРегистрации.Модуль(205)}: Поле объекта не обнаружено (EventName).

    Reply
  67. sound

    Стал искать журнальчик для себя, среди прочих, и по крайней мере из того, что пока удалось найти, Ваш лидирует по качеству исполнения и кода, а еще вообще сама идея хорошая. Я бы еще добавил для себя вот такое http://infostart.ru/public/19949/, и тогда было бы вообще все просто зашибись. Однако у меня оно на 8.2 так и не заработало 😥

    Reply
  68. sound

    Люди-и-и, хоть у кого-нибудь эта штука на 8.2 работает а? Или все на 8.1 сидят?

    Reply
  69. artbear

    (68) У меня заработало, недавно перевел конфу на 8.1 и решил проблему неверной работы.

    Reply
  70. sound

    (69) Поздно, я уже себе переписал 🙂

    Reply
  71. yushmakovmv

    Интересная разработка.

    Reply
  72. wwizard

    У меня 8,2

    При сравнении и объединении конфигураций, база перестала работать….

    т.е. она загружается но ни один документ, справочник не работает.

    Reply
  73. Abenefic

    хм…

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *