Перейти к содержимому


import_data + cron - как происходит перезапуск скрипта?


Сообщений в теме: 5

#1 Givik

    Участник

  • Пользователи
  • PipPip
  • 17 сообщений
  • Пол:Мужчина

Отправлено 18 Июль 2014 - 12:28

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

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

$some_query = "SELECT что-то INTO OUTFILE ... FROM ..."; // результат запроса к другой базе сохраняется в файл $export_file_name
if ($export_result = mysqli_query($another_db_conn, $some_query)) {
  echo '   Exported okay, starting import to CB'.PHP_EOL;
  import_data('Таблица в КБ', 'Шаблон импорта', $export_file_name); // объем большой!
  echo '   Imported to CB okay'.PHP_EOL;
}

Если результирующий файл небольшого объема - import_data успевает отработать за один раз. В логах вижу записи:
2014-07-18 03:01:09 -
Exported okay, starting import to CB
Done. 0 records inserted, 194 records updated. Imported to CB okay


Но если файл получается большой, то проиходят странности. Во-первых, ни одно "echo" не попадает в лог, во-вторых, в логе я вижу странную запись типа (скрипт по крону стартует каждый час в 00 минут):
2014-07-18 04:36:00 - TERMINATED TASK FROM 2014-07-18 04:02:20 - и все!!!

По логике работы скрипта, я вижу, что все, что после import_data - не выполнилось (не выполнились другие запросы, не создались файлы).

Судя по документации, если скрипт не укладывается в отведенное время, он перезапускается. Но как это происходит? И почему падает выполнение import_data?

#2 CbCoder

    Активный участник

  • Программист ООО "КБ"
  • PipPipPip
  • 8 759 сообщений
  • Пол:Мужчина
  • Город:Казань

Отправлено 18 Июль 2014 - 12:43

Цитата

в логе я вижу странную запись

Что в ней странного? Стандартное сообщение о прерывании задачи по причине таймаута. И судя по тому, что ваше echo перед import_data не отобразилось, прерывание произошло не во время импорта, а перед ним. Т.е. очевидно, вылетает ваш запрос выше, а не собственно импорт (потому и перезапуска не было).

#3 Givik

    Участник

  • Пользователи
  • PipPip
  • 17 сообщений
  • Пол:Мужчина

Отправлено 19 Июль 2014 - 00:23

Хорошо, переделал скрипт. Теперь сначала выполняются все запросы к сторонней системе, потом стартуют все импорты в КБ:

// Запускаем запросы, экспортирующие данные из Kayako в CSV-файлы
echo '  Exporting Users from Kayako...'.PHP_EOL; 
if ($users_result = mysqli_query($kayako_conn, $users_query)) {
  echo '  Users exported OK'.PHP_EOL;
} else {
  echo '  Users export error: '.mysqli_error($kayako_conn).PHP_EOL;
}
echo '  Exporting Tickets from Kayako...'.PHP_EOL; 
if ($tickets_result = mysqli_query($kayako_conn, $tickets_query)) {
  echo '   Tickets exported OK'.PHP_EOL;
} else {
  echo '  Tickets export error: '.mysqli_error($kayako_conn).PHP_EOL;
}

// Запускаем импорт из файлов в КБ
if ($users_result) {
  echo '  Importing Users to CB...'.PHP_EOL;
  import_data("Пользователи", "kayako", $users_file_name);
  echo '   Users imported OK'.PHP_EOL;
}
if ($tickets_result) {
  echo '  Importing Tickets to CB...'.PHP_EOL;
  import_data('Заказы файлов', 'kayako tickets', $tickets_file_name); // ВОТ ТУТ ИМПОРТИРУЕТСЯ БОЛЬШОЙ ФАЙЛ!!!
  echo '   Tickets imported OK'.PHP_EOL;
}

После запуска в логах вижу следующее:
Exporting Users from Kayako...
Users exported OK
Exporting Tickets from Kayako...
Tickets exported OK
Importing Users to CB...
Done. 1 records inserted, 195 records updated. Users imported OK
Importing Tickets to CB...
23% Tickets imported OK

ну и далее все последующие "echo" по скрипту

Но вот что самое интересное:
1. В логах отсутствует запись типа "X records inserted, Y records updated"
2. В базе КБ вижу, что обновились НЕ ВСЕ записи, которые были в импортируемом файле
3. Запускаю импорт из этого же файла вручную (выбираю вручную тот же шаблон), проверяю в КБ - теперь ВСЕ записи обновлены. И импорт выполнялся ощутимо дольше, чем через скрипт крона.

Делаю вывод - import_data в скрипте прервалась на 23%, но при автоматическом перезапуске скрипта не возобновилась. Как такое возможно?

#4 CbCoder

    Активный участник

  • Программист ООО "КБ"
  • PipPipPip
  • 8 759 сообщений
  • Пол:Мужчина
  • Город:Казань

Отправлено 19 Июль 2014 - 13:00

Понятия не имею. Но есть подозрение, что ваш код в задании перед импортом занимает существенное время, из-за чего функция импорта не может адекватно оценить время до конца скрипта, и соответственно вовремя перезапустить себя. Кроме того, я не уверен что при перезапуске не будет выполнено все задание целиком заново (чего вам вряд ли надо), хотя тут точно не знаю. Т.е. вывод в том, что не стоит рассчитывать на перезапуск функции импорта, если вы используете его в каком-то сложном коде, где кроме импорта еще что-то есть (или производится сразу несколько операций импорта). Можно разве что попробовать поделить этот код на несколько заданий крон, и импорт производить отдельно в своих заданиях. Других вариантов не вижу.

#5 Givik

    Участник

  • Пользователи
  • PipPip
  • 17 сообщений
  • Пол:Мужчина

Отправлено 19 Июль 2014 - 14:20

К сожалению, скрипты крона нельзя выстраивать в цепочки (выполнился скрипт А, затем скрипт В и т.д.). А данные связаны, т.е. обязательно нужно, чтобы таблица А обновилась перед обновлением таблицы В. Поэтому и пишу в одном скрипте.
Какие еще есть варианты решения?

#6 CbCoder

    Активный участник

  • Программист ООО "КБ"
  • PipPipPip
  • 8 759 сообщений
  • Пол:Мужчина
  • Город:Казань

Отправлено 19 Июль 2014 - 14:48

Цитата

К сожалению, скрипты крона нельзя выстраивать в цепочки

Почему нельзя? Если правильно задать расписание (по часам например), то теоретически можно. Хотя это конечно не лучший вариант, но есть и другой: никто не мешает вам сохранять где-то последовательность выполнения этапов, например в БД или в файле. И соответственно, в начале очередного задания смотреть, какой этап пройден. Если предыдущий - запускаем задание, не наш - выходим до следующей проверки.





Количество пользователей, читающих эту тему: 1

0 пользователей, 1 гостей, 0 анонимных