Новый режим реструктуризации (обновление базы данных на сервере в режиме v2)




Принцип обмена данными из 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='\

46 Comments

  1. nyam-nyam

    Ещё по теме для тех кто тюнингует 1С+MS SQL: https://its.1c.ru/db/metod8dev/content/5945/hdoc.

    Reply ↓
  2. Dach

    (1) да, весьма в тему, спасибо!

    Reply ↓
  3. user612295_death4321

    Буду тестировать скоро отключение режима совместимости 8.2))) БД почти 3 ТБ.

    Reply ↓
  4. vcv

    Двойственные чувства.

    С одной стороны слава тебе Господи, наконец-то 1С сподобилась взяться за то, что куча народа ждало еще со времён 7.7. С другой стороны тут и Java, тут и Powershell… А сплясать в водолазном костюме в гамаке не надо?

    Reply ↓
  5. slawanix

    (4) аналогичные чувства… только обрадоваться хотел, но остался вопрос, почему нельзя сделать это всё прямо из платформы, по кнопке «сделать всё хорошо»?

    Reply ↓
  6. Vladimir Litvinenko

    (4) Java — это отголоски наработок по платформе 1C 8.4. Развитие этой версии идет медленно и новостей давно не слышно, но ее наработки постепенно появляются в 8.3. На Java никто писать не заставляет, а представить машину без JRE сейчас сложно. И судя по всему с Java придется дружить всё больше — EDT, сервер взаимодействия и т.д.

    Powershell для примера же приведен. Там кроме команды запуска 1С с параметрами «UpdateDBCfg -Server -v2» и нет ничего, одна консольная команда. Не внешнюю же обработку для выполнения одной консольной команды писать…

    Reply ↓
  7. palsergeich

    Я один раз пробовал.

    Мне вывело сообщение ошибка и на какой то внутренний модуль.

    Гугл сказал что ничего не светит. я сказал ок и по старому за 6 часов обновился.

    Обидно конечно.

    Reply ↓
  8. silberRus

    Интересно что за данные в базе на 1тб.

    Reply ↓
  9. DrAku1a

    (6)

    Там кроме команды запуска 1С с параметрами «UpdateDBCfg -Server -v2» и нет ничего

    CMD не подойдёт?

    Reply ↓
  10. buganov

    (8)скорее всего продажи, чеки, заказы на перемещение / перемещения на магазины.

    У нас база 3 Тб

    Reply ↓
  11. dsdred

    (8)Размер базы обычной небольшой торговой сети, может быть еще с небольшим производством…

    Reply ↓
  12. Dach

    Можно и cmd. Друзья, конечно это не одна кнопка «сделать всё хорошо», но уже существенный задел. База — склад, продажи, логистика. Плюс у нас ещё и РИБ. Механизм обновления активно используем, все работает… На ИТС информации мало, поэтому посчитал нужным поделиться опытом и отчитаться об успехе) в дальнейшем неплохо было бы иметь возможность обновляться пакетно с возможностью логгировать ход обновления

    Reply ↓
  13. Fox-trot

    (12)пока логирование обновления можно наблюдать на стороне базы данных

    Reply ↓
  14. Xershi

    У конфигурации режим совместимости был 8.3.11? Или ниже?

    Reply ↓
  15. Dach

    (14) режим совместимости был выключен. Но думаю, в режиме совместимости 8.3.11 должно отработать

    Reply ↓
  16. Xershi

    (15) значит как и завялено при режиме совместимости 8.3.10 все будет по старому!

    Reply ↓
  17. comol

    О даааа!!!!! Это случилось! В 1С выучили Alter Table!

    Reply ↓
  18. comol

    Малину портит только » На сервере 1С обязательно должен быть установлен runtime Java 8″. Вопрос «зачем так» наверное риторический…

    Reply ↓
  19. Dach

    (18) весь «интеллект» умных скриптов T-SQL написан на Java, в недрах платформы, насколько я понял ))

    Reply ↓
  20. acanta

    (19) т.е. можно в принципе написать левый скрипт на Java, который реструктуризует базу под новую конфигурацию и зальет туда измененный cf с гитхаба или с какого нибудь каталога?

    И все будет работать?

    Reply ↓
  21. comol

    (19) в недрах платформы Java нет, иначе мы бы это уже «почувствовали».

    Пока надеюсь что и не будет.

    Reply ↓
  22. comol

    (20) можно декомпильнуть то что написано, подправить и юзать как хочется теперь 🙂

    Reply ↓
  23. acanta

    (23) на каждое добавление булева не надекомпилируешься. Но сама идея о неразрывном совмещении данных в базе и их интерфейса достаточно спорная.

    При том, что на все итоги и индексы, целостность которых якобы гарантирует платформа, существуют процедуры SQL, выполняющие пересчеты.

    Reply ↓
  24. Dach

    (22) ну как-то же она тексты скриптов собирает, в зависимости от выполненных действий в конфигураторе

    Reply ↓
  25. acanta

    (26) мы бы тоже хотели знать как и почему alter возник только сейчас. Исторически сложилось, что реструктуризация выполнялась таким образом в DBF. Сначала все измененные файлы складывались в папку NewStru, затем копировались вместо находящихся в базе. Почти цитирую старый мануал: при возникновении сбоя на первом этапе файлы в базе будут первоначальных вариантов и никакие данные не будут утеряны.

    При возникновении сбоя на втором этапе часть данных в базе может стать некорректной, но всегда есть возможность скопировать файлы из NewStru и завершить процесс реструктуризации вручную. Исходили из положения что бакап и изменение структуры в процессе работы с DBF по-горячему сделать невозможно, а программист, обслуживающий конфигурацию не полезет в dbf и работу платформы, но точно знает основы работы с файлами в файловом менеджере.

    В SQL есть возможность добавить колонку в таблицу в процессе работы. Немонопольно. Это не проблема для SQL, это проблема конфигуратора, который не умеет работать одновременно с разными версиями данных (до и после) какой то реструктуризации.

    Reply ↓
  26. Repich

    (7)

    Вот такое у меня сейчас. Ковыряемся. Ради спортивного интереса хочу докопаться до причин.

    В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка

    по причине:

    Критическая ошибка работы Java-процесса.

    Путь к Java: C:Program FilesJavajre1.8.0_181injava.exe

    Действие: prepare

    Process ID: 22296

    Код возврата: 1

    Ошибка: Exception in thread «main» java.lang.IllegalStateException: Duplicate key ae4a0c5e-f97b-4cf4-96d8-c040bf8e222b

    at java.util.stream.Collectors.lambda$throwingMerger$0(Unknown Source)

    at java.util.HashMap.merge(Unknown Source)

    at java.util.stream.Collectors.lambda$toMap$58(Unknown Source)

    at java.util.stream.ReduceOps$3ReducingSink.accept(Unknown Source)

    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(Unknown Source)

    at java.util.stream.AbstractPipeline.copyInto(Unknown Source)

    at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)

    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)

    at java.util.stream.AbstractPipeline.evaluate(Unknown Source)

    at java.util.stream.ReferencePipeline.collect(Unknown Source)

    at com._1c.dmf.v8.converters.parameters.documentjournal.GraphContent.<init>(GraphContent.java:24)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeGraphContent(ConfigurationModelParser.java:352)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeValue(ConfigurationModelParser.java:208)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeParameter(ConfigurationModelParser.java:172)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeAttributeParameter(ConfigurationModelParser.java:155)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeEntityParameters(ConfigurationModelParser.java:139)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeParameters(ConfigurationModelParser.java:112)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.parse(ConfigurationModelParser.java:92)

    at com._1c.dmf.v8.internal.integration.Arguments.getOldModel(Arguments.java:84)

    at com._1c.dmf.v8.internal.integration.DmfService.prepareMigration(DmfService.java:64)

    at com._1c.dmf.v8.cli.Migration.run(Migration.java:90)

    at com._1c.dmf.v8.cli.Migration.main(Migration.java:65)

    Reply ↓
  27. palsergeich

    (28)

    at java.util.HashMap.merge(Unknown Source)

    Да что то очень похожее.

    Причем все базы кроме нужной реструктурировались новым методом нормально.

    Но там было не к спеху, и я просто сделал по старинке.

    Изменений очень много было, может в этом была проблема?

    Reply ↓
  28. Dach

    (28) поставь Яву не 181, а 171 или младше

    Reply ↓
  29. philya

    (21) я на java драйвера для фискальных регистраторов пишу, очень удобно, т.к. один код работает под виндой, линуксом и андроидом. Что я делаю не так? С++ я тоже умею.

    Reply ↓
  30. 7OH

    (31) драйвера или обёртки для готовых dllso ?

    Reply ↓
  31. philya

    (32) библиотеки работы с com/usb готовые, драйвера мои что-то типа….

    @Override

    public ByteBuffer getCommand() {

    ByteBuffer data = ByteBuffer.allocate(12 + cashier.length() + cashierFiscalId.length());

    data.order(ByteOrder.LITTLE_ENDIAN);

    data.putShort((short) 2); // отчет об открытии смены

    data.putShort((short) (4 + cashier.length() + 4 + cashierFiscalId.length()));

    data.putShort((short) 1021);

    data.putShort((short) cashier.length());

    data.put(cashier.getBytes(Charset.forName(«IBM866»)));

    data.putShort((short) 1203);

    data.putShort((short) cashierFiscalId.length());

    data.put(cashierFiscalId.getBytes(Charset.forName(«IBM866»)));

    setData(data);

    return super.getCommand();

    }

    Reply ↓
  32. Andrefan

    (0) Спасибо за интересный материал! Не подскажите, режим совместимости с 8.2.13 возможно заставить работать этот механизм?

    Reply ↓
  33. Dach

    (34) к сожалению, нет. Вам придется прибегать к другим методам… О том, как добавлять колонки и индексы в большие таблицы БД — куча статей есть на ИС, в том числе и у меня (не реклама)

    Reply ↓
  34. Kamikadze

    Надо добавить, что для клиент — серверного варианта базы нужно перезапустить службу сервера 1С

    У меня возникла ошибка

    В процессе обновления конфигурации базы данных при работе механизма реструктуризации второй версии произошла критическая ошибка

    по причине:

    При работе механизма реструктуризации второй версии возникла ошибка. Код возврата: 1. Операция: execute.

    Версия платформы 8.3.13.1513

    Reply ↓
  35. dmarenin

    (0) молодцы! ждем вьюхи

    Reply ↓
  36. Evil Beaver

    (21) Ну при всей моей нелюбви к Джаве, я бы все-таки не стал называть ее мусором 🙂 Тот же Apache Kafka на ней написан и шустр до безобразия.

    Reply ↓
  37. nytlenc

    (2) и еще в догонку по теме «для тех кто тюнингует 1С+MS SQL» http://v8.1c.ru/predpriyatie/questions_licence.htm#lrvs1cpp

    это к последнему апдейту

    ВАЖНО: Если обновление по v2 падает с ошибкой — одна из причин может быть в том, что в вашей БД есть индексы, отличные от стандартных платформенных (добавленные вручную) — их необходимо физически удалить (именно удалить, а не отключить) перед запуском обновления.
    Reply ↓
  38. 3vs

    А, говорят, Java теперь платная, Oracle денег просит за её использование

    не в домашнем применении.

    Reply ↓
  39. Antonov.AV

    (4) я думал только у меня такое ощущение)

    Reply ↓
  40. kauksi

    почти типовая УПП…

    В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка

    по причине:

    Критическая ошибка работы Java-процесса.

    Путь к Java: C:Program Files (x86)Javajre1.8.0_221injava.exe

    Действие: prepare

    Process ID: 2660

    Код возврата: 1

    Ошибка: Exception in thread «main» java.lang.OutOfMemoryError: Java heap space

    Reply ↓
  41. kauksi

    Эта проблема решилась добавлением опции JavaOpts=-Xmx2048m в conf.cfg, но теперь ошибка без расшифровки

    Критическая ошибка работы Java-процесса.

    Путь к Java: C:Program Files (x86)Javajre1.8.0_221injava.exe

    Действие: prepare

    Process ID: 3392

    Код возврата: 1

    Ошибка:

    Reply ↓
  42. kauksi

    повышение режима совместимости УПП до 8.3.1 результатов не дало. Видать сырая еще опция

    Reply ↓
  43. Dach

    (44) механизм работает с версии 8.3.11. Совместимость должна быть не ниже этой версии

    Reply ↓
  44. bforce

    (45)

    Неверно. У меня в режиме совместимости 8.3.6 отрабатывает.

    Reply ↓
  45. Andreynikus

    (1) Ирония в том, что в старом механизме реструктуризации указание MAXDOP=0 используется по умолчанию, она добавлена в качестве опции в запросе на создание индекса.

    А вот в новом механизме, который описан в данной статье, разработчики почему-то забыли эту опцию включить в запрос и если в настройках сервера MAXDOP равен 1, то реструктуризация будет медленнее чем хотелось бы . Возможно следует в статье 4-м пунктом добавить, что включение на сервере MAXDOP=0 на время реструктуризации, дополнительно ускорит этот процесс.

    Reply ↓

Leave a Comment

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