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




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2024-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 не будет опубликован. Обязательные поля помечены *