[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Почему останавливается скрипт?
Strannik
Добрый вечер.

в php.ini настройки
max_execution_time = 144000
max_input_time = 144000

делаю такую штучку:


ignore_user_abort(true);
set_time_limit(0);
$i=0;
conn();
$sql_dump="SELECT * FROM `dump` WHERE `id`='1'";
$res_dump=mysql_query($sql_dump);
if(!$res_dump||mysql_num_rows($res_dump)<1){$sql_dump2="INSERT INTO `dump` (`text`,`status`) VALUES ('Идет обновление базы данных...','yes')";}else{$sql_dump2="UPDATE `dump` SET `text`='Идет дамп...',`status`='yes' WHERE `id`='1'";}
$res_dump2=mysql_query($sql_dump2);
$r1='';$r2='';$r3='';$r4='';
$filename="csv.csv";
$handle = fopen("$filename", "r");
$count_rows=0;
$import='';
$error1='';
$error2='';
$error3='';
$error4='';
while (($data = fgetcsv($handle, 1000000, ";")) !== FALSE)
{
$count_rows++;
$oldperiod = strtotime($data[1]);
$newperiod = date('Y-m-d H:i:s', $oldperiod);

$olddate_create = strtotime($data[15]);
$newdate_create = date('Y-m-d H:i:s', $olddate_create);

$oldperiodmeter_reading = strtotime($data[13]);
$newperiodmeter_reading = date('Y-m-d H:i:s', $oldperiodmeter_reading);

if($data[2]!=''){
$sql0="SELECT * FROM `balans` WHERE `period`='$newperiod' AND `idn`='$data[2]'";
$res0=mysql_query($sql0);
if(!$res0||mysql_num_rows($res0)<1){$importone="INSERT INTO `balans`(`idn`, `period`, `start_saldo`, `earn_m`, `earn_r`, `pay`, `finish_saldo`) VALUES ('$data[2]', '$newperiod', '$data[5]', '$data[7]', '$data[6]', '$data[8]', '$data[9]')";}
else{$importone="UPDATE `balans` SET `start_saldo` = '$data[5]', `earn_m` = '$data[7]', `earn_r` = '$data[6]', `pay` = '$data[8]', `finish_saldo` = '$data[9]' WHERE `idn` ='$data[2]' AND `period`='$newperiod'";}
$res_importone=mysql_query($importone) or die(mysql_error($res_importone));//$error1.=mysql_error($res_import1);
$sql0e="SELECT * FROM `equipment` WHERE `idn`='$data[2]'";
$res0e=mysql_query($sql0e);
if(!$res0e||mysql_num_rows($res0e)<1){if($data[10]!='0'){$importtwo="INSERT INTO `equipment`(`idn`, `type`, `model`, `date_create`, `serial_number`, `date_of_sealing`, `seal_number`, `state`) VALUES ('$data[2]', '', '$data[11]', '$newdate_create', '$data[12]', '', '', '')";$res_importtwo=mysql_query($importtwo) or die(mysql_error($res_importtwo));}}
else{$importtwo="UPDATE `equipment` SET `type`='',`model`='$data[11]',`date_create`='$newdate_create',`serial_number`='$data[12]',`date_of_sealing`='', `seal_number`='',`state`=''";$res_importtwo=mysql_query($importtwo) or die(mysql_error($res_importtwo));}
$sqlimport_meter_reading="SELECT * FROM `meter_reading` WHERE `value` = '$data[14]' AND `period`='$newperiodmeter_reading' AND `idn`='$data[2]'";
$resimport_meter_reading=mysql_query($sqlimport_meter_reading);
if(!$resimport_meter_reading||mysql_num_rows($resimport_meter_reading)<1)
{if($data[10]=='1'&&$data[13]!=''){$importtree="INSERT INTO `meter_reading`(`idn`, `period`, `value`, `pay_type`) VALUES ('$data[2]', '$newperiodmeter_reading', '$data[14]', '$data[10]')";$res_importtree=mysql_query($importtree) or die(mysql_error($res_importtree));//$error3.=mysql_error($res_import3);
}}
$sql="SELECT * FROM `user_info` WHERE `account` = '$data[2]'";
$res=mysql_query($sql);
if(!$res||mysql_num_rows($res)<1)
{$importfour="INSERT INTO `user_info`(`fio`, `account`, `living_space`, `occupancy`, `adress`, `telefone`, `mobile`, `email`, `icq`, `password`, `password_temp`, `status`) VALUES ('".mysql_real_escape_string($data[3])."', '$data[2]', '', '', '$data[4]', '', '', '', '', '', '', 'user')";}
else{$importfour="UPDATE `user_info` SET `fio` = '$data[3]', `adress` = '$data[4]' WHERE `account` ='$data[2]'";}
$res_importfour=mysql_query($importfour) or die(mysql_error($res_importfour));//$error4.=mysql_error($res_import4);*/
}$i++; echo $i.'<br>';
}


скрипт обрабатывает файл до 2187 строки и останавливается,
т.е. просто пишет цифры в ряд до 2187:
1
2
3
....
2187

а почему понять пока не могу...
кто знает в чем может быть причина?

P.S.: смотрел логи сервера, ошибок нет.
P.P.S.: код конечно слишком накрученный, но по-другому никак...



Спустя 37 секунд (14.08.2012 - 23:20) inpost написал(а):
зачем дублировать? Я тебе там ответил уже.

Спустя 39 минут, 21 секунда (14.08.2012 - 23:59) Strannik написал(а):
вынес оттуда, там тема несколько другая.
сделал обработчик на запись в файл, но ошибок не записывает...

Как можно проверить в чем дело?

код:


ignore_user_abort(true);
set_time_limit(0);
$i=0;
conn();
$sql_dump="SELECT * FROM `dump` WHERE `id`='1'";
$res_dump=mysql_query($sql_dump);
if(!$res_dump||mysql_num_rows($res_dump)<1){$sql_dump2="INSERT INTO `dump` (`text`,`status`) VALUES ('Идет обновление базы данных...','yes')";}else{$sql_dump2="UPDATE `dump` SET `text`='Идет дамп...',`status`='yes' WHERE `id`='1'";}
$res_dump2=mysql_query($sql_dump2);
$r1='';$r2='';$r3='';$r4='';
$filename="abase/work/base_csv.csv";
$handle = fopen("$filename", "r");

$fperrors = fopen("errors.txt", "a"); // Открываем файл в режиме записи
$errors='';
$count_rows=0;
while (($data = fgetcsv($handle, 1000000, ";")) !== FALSE)
{
$count_rows++;
$oldperiod = strtotime($data[1]);
$newperiod = date('Y-m-d H:i:s', $oldperiod);

$olddate_create = strtotime($data[15]);
$newdate_create = date('Y-m-d H:i:s', $olddate_create);

$oldperiodmeter_reading = strtotime($data[13]);
$newperiodmeter_reading = date('Y-m-d H:i:s', $oldperiodmeter_reading);

if($data[2]!=''){
$sql0="SELECT * FROM `balans` WHERE `period`='$newperiod' AND `idn`='$data[2]'";
$res0=mysql_query($sql0);
if(!$res0||mysql_num_rows($res0)<1){$importone="INSERT INTO `balans`(`idn`, `period`, `start_saldo`, `earn_m`, `earn_r`, `pay`, `finish_saldo`) VALUES ('$data[2]', '$newperiod', '$data[5]', '$data[7]', '$data[6]', '$data[8]', '$data[9]')";}
else{$importone="UPDATE `balans` SET `start_saldo` = '$data[5]', `earn_m` = '$data[7]', `earn_r` = '$data[6]', `pay` = '$data[8]', `finish_saldo` = '$data[9]' WHERE `idn` ='$data[2]' AND `period`='$newperiod'";}
$res_importone=mysql_query($importone); if(!$res_importone){$errors.=mysql_error($res_importone);}
$sql0e="SELECT * FROM `equipment` WHERE `idn`='$data[2]'";
$res0e=mysql_query($sql0e);
if(!$res0e||mysql_num_rows($res0e)<1){if($data[10]!='0'){$importtwo="INSERT INTO `equipment`(`idn`, `type`, `model`, `date_create`, `serial_number`, `date_of_sealing`, `seal_number`, `state`) VALUES ('$data[2]', '', '$data[11]', '$newdate_create', '$data[12]', '', '', '')";$res_importtwo=mysql_query($importtwo); if(!$res_importtwo){$errors.=mysql_error($res_importtwo);}}}
else{$importtwo="UPDATE `equipment` SET `type`='',`model`='$data[11]',`date_create`='$newdate_create',`serial_number`='$data[12]',`date_of_sealing`='', `seal_number`='',`state`=''";$res_importtwo=mysql_query($importtwo); if(!$res_importtwo){$errors.=mysql_error($res_importtwo);}}
$sqlimport_meter_reading="SELECT * FROM `meter_reading` WHERE `value` = '$data[14]' AND `period`='$newperiodmeter_reading' AND `idn`='$data[2]'";
$resimport_meter_reading=mysql_query($sqlimport_meter_reading);
if(!$resimport_meter_reading||mysql_num_rows($resimport_meter_reading)<1)
{if($data[10]=='1'&&$data[13]!=''){$importtree="INSERT INTO `meter_reading`(`idn`, `period`, `value`, `pay_type`) VALUES ('$data[2]', '$newperiodmeter_reading', '$data[14]', '$data[10]')";$res_importtree=mysql_query($importtree); if(!$res_importtree){$errors.=mysql_error($res_importtree);}//$error3.=mysql_error($res_import3);
}}
$sql="SELECT * FROM `user_info` WHERE `account` = '$data[2]'";
$res=mysql_query($sql);
if(!$res||mysql_num_rows($res)<1)
{$importfour="INSERT INTO `user_info`(`fio`, `account`, `living_space`, `occupancy`, `adress`, `telefone`, `mobile`, `email`, `icq`, `password`, `password_temp`, `status`) VALUES ('".mysql_real_escape_string($data[3])."', '$data[2]', '', '', '$data[4]', '', '', '', '', '', '', 'user')";}
else{$importfour="UPDATE `user_info` SET `fio` = '$data[3]', `adress` = '$data[4]' WHERE `account` ='$data[2]'";}
$res_importfour=mysql_query($importfour); if(!$res_importfour){$errors.=mysql_error($res_importfour);}//$error4.=mysql_error($res_import4);*/
if($errors!=''){
$test = fwrite($fperrors, $errors);
if ($test) echo 'Данные в файл успешно занесены.';}
}
$i++; echo $i.'<br>';
}fclose($fperrors);

Спустя 5 минут, 14 секунд (15.08.2012 - 00:05) inpost написал(а):
А туда хоть что-то записывается? Может права не выставил?

Спустя 5 минут, 34 секунды (15.08.2012 - 00:10) Strannik написал(а):
да, проверил только что:
$errors='start';
и загнал в файл очень много start

Спустя 21 минута, 5 секунд (15.08.2012 - 00:31) Strannik написал(а):
похоже сервер перегрузился на хостинге. а на своем сервере как проверить перегрузку сервера? и как понять что соединение с базой было потеряно?

Спустя 21 минута, 27 секунд (15.08.2012 - 00:53) inpost написал(а):
Strannik
так же само, файл проверяй smile.gif

Спустя 1 час, 14 минут, 19 секунд (15.08.2012 - 02:07) Strannik написал(а):
inpost
в том то и дело - файл пуст, ошибок в нем нет(

Спустя 2 минуты (15.08.2012 - 02:09) inpost написал(а):
Strannik
Пуст, даже "и загнал в файл очень много start " нет?

Спустя 10 минут, 22 секунды (15.08.2012 - 02:19) Strannik написал(а):
я про то, что он ошибки не записывает. как понять, записал я к примеру "очень много start", а что мне это дает? максимум узнаю строку где обрыв, а дальше?

Спустя 13 минут, 32 секунды (15.08.2012 - 02:33) inpost написал(а):
Strannik
Я хочу быть уверенным, что у тебя на твоём сервере (где нет ограничения на лимит выполнения по времени скрипта) всё работает, включая запись в файл.
А вообще, сделай рекурсию, отработал X записей, через соккеты вызвал самого себя и завершил данный скрипт. Там как раз можно вызвать файл и не дожидаясь завершения работы завершить!

Спустя 18 минут, 43 секунды (15.08.2012 - 02:52) Strannik написал(а):
а про "через соккеты вызвал самого себя и завершил данный скрипт"
можно подробнее? где можно почитать?

Спустя 22 минуты, 37 секунд (15.08.2012 - 03:14) inpost написал(а):
google: соккеты. smile.gif По крайней мере я так читал smile.gif

Спустя 10 часов, 5 минут, 11 секунд (15.08.2012 - 13:20) Strannik написал(а):
логи посмотрел, происходит обрыв соединения с базой данных(дошел до 95 000 строк). кто-нибудь знает как предовтратить или почему сервер может сбрасывать соединение(может настройках что-нибудь)?

Спустя 32 минуты, 27 секунд (15.08.2012 - 13:52) inpost написал(а):
Strannik
Увы, не подскажу, но там лимит по времени на открытое соединение, через Х времени сбрасывается. Об этом я тебе и говорил выше, перехватить разрыв соединения с БД надо и снова открыть заново. У меня как раз такое же было, когда скрипт отрабатывал 20 минут.

Спустя 2 минуты, 5 секунд (15.08.2012 - 13:54) Strannik написал(а):
у меня скрипт отрабатывает несколько часов)

Спустя 1 минута, 16 секунд (15.08.2012 - 13:55) Strannik написал(а):
и еще.. лимит по времени на открытое соединение задается в параметрах сервера? если да, то где?

Спустя 49 минут, 14 секунд (15.08.2012 - 14:45) sergeiss написал(а):
Ты для ввода КАЖДОЙ строки делаешь запрос к БД, а потом решаешь, надо ли делать INSERT или UPDATE? Это верный способ убить сервер smile.gif

1. Забудь всё, что ты сделал в этом скрипте.
2. Прочитай про опцию ON DUPLICATE KEY UPDATE, которая имеется в Мускуле для INSERT'а.
3. Прочитай про LOAD DATA INFILE, загрузку данных прямо из файла в таблицу.
4. Переделай скрипт с активным использованием этих возможностей.

Я думаю, что если ты используешь эти фичи, то твои данные начнут заливаться за очень короткое время.

Спустя 20 минут, 15 секунд (15.08.2012 - 15:05) Strannik написал(а):
спасибо. попробую.

Спустя 22 минуты, 18 секунд (15.08.2012 - 15:27) Strannik написал(а):
а как данную проверку изменить:

$sql0="SELECT * FROM `balans` WHERE `period`='$newperiod' AND `idn`='$data[2]'";
$res0=mysql_query($sql0);
if(!$res0||mysql_num_rows($res0)<1){$import1="INSERT INTO `balans`(`idn`, `period`, `start_saldo`, `earn_m`, `earn_r`, `pay`, `finish_saldo`) VALUES ('$data[2]', '$newperiod', '$data[5]', '$data[7]', '$data[6]', '$data[8]', '$data[9]')";$res_import1=mysql_query($import1);}
else{
$i1=mysql_fetch_assoc($res0);
if($i1['start_saldo']!=$data[5]||$i1['earn_m']!=$data[7]||$i1['earn_r']!=$data[6]||$i1['pay']!=$data[8]||$i1['finish_saldo']!=$data[9]){
$import1="UPDATE `balans` SET `start_saldo` = '$data[5]', `earn_m` = '$data[7]', `earn_r` = '$data[6]', `pay` = '$data[8]', `finish_saldo` = '$data[9]' WHERE `idn` ='$data[2]' AND `period`='$newperiod';"
}


здесь нужно проверить если совпадает пользователь и дата тогда update, а если нет тогда insert
это при том, что уникальным могу сделать только поле period..

как это сделать?

Спустя 9 минут, 16 секунд (15.08.2012 - 15:36) Strannik написал(а):
и еще, т.е получается сначала записать дамп в sql файл на сервере, а потом через LOAD DATA LOCAL INFILE забросить?

а как указать в скрипте путь до файла?
т.е. к примеру dump.sql будет находиться в одной директории со скриптом.
указать просто dump.sql
$result = mysql_query("LOAD DATA LOCAL INFILE 'dump.sql' INTO TABLE 'zoznam' FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\' LINES TERMINATED BY '\r\n'");


или нужен DocumentRoot?

$result = mysql_query("LOAD DATA LOCAL INFILE '/hsphere/local/home/site.ru/dump.sql' INTO TABLE 'zoznam' FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\' LINES TERMINATED BY '\r\n'");


Как правильно?

Спустя 11 минут, 3 секунды (15.08.2012 - 15:47) inpost написал(а):
Strannik
INSERT делай по 50-100 записей за 1 раз.

Спустя 13 минут, 49 секунд (15.08.2012 - 16:01) Strannik написал(а):
inpost
в этом же и проблема, мне сначала нужно проверить, если есть строка со значениями `period`='$newperiod' AND `idn`='$data[2]', тогда делаем insert, иначе update, а теперь представь если обрабатывать весь код по 50-100 записей, не будет ли это лишней нагрузкой?

P.S.: да и к тому же я не знаю как внутри while (($data = fgetcsv($handle, 1000000, ";")) !== FALSE){} пустить обработчик чтобы он запускал импорт по 50 записей. теоретически конечно можно сделать запись в файл, после 50 записи запускать считывание файла и импорт всех строк из него, но мне кажется это очень напряжно будет...

Спустя 49 минут, 25 секунд (15.08.2012 - 16:51) inpost написал(а):
INSERT ON DUPLICATE UPDATE - это используй в таком случае smile.gif
Или даже сам факт того, что после SELECT ты узнаешь, что такой записи нет - то это хороший повод поместить INSERT в общий пакет, чтобы потом пакетом заливать.

Спустя 3 часа, 37 минут, 54 секунды (15.08.2012 - 20:29) sergeiss написал(а):
Цитата (Strannik @ 15.08.2012 - 17:36)
и еще, т.е получается сначала записать дамп в sql файл на сервере, а потом через LOAD DATA LOCAL INFILE забросить?

Не в SQL файл, а в обычный текстовый. Найди примеры, как это делается!!! В и-нете их много. Впрочем, нормального хэлп достаточно.

Цитата (Strannik @ 15.08.2012 - 17:36)

а как указать в скрипте путь до файла?

Пусть к файлу отсчитывается с точки зрения файловой системы компьютера, а не относительно сайта! Как именно - читай хэлп, там разные варианты возможно.

Цитата (Strannik @ 15.08.2012 - 18:01)
в этом же и проблема, мне сначала нужно проверить, если есть строка со значениями

...ON DUPLICATE KEY UPDATE... именно это и делает, без лишних (ненужных) телодвижений с твоей стороны. Ты уж прочитай сам про эту конструкцию, что ли smile.gif
Правда, эта хрень работает с обычным апдейтом, а не с массовой загрузкой.
Впрочем, можно сделать триггеры, которые при массированной загрузке LOAD DATA INFILE будут работать не хуже, чем ON DUPLICATE KEY с индивидуальными инсертами. Та же проверка получится на существование данных, но она будет делаться внутри Мускуля, не надо будет в ПХП ничего лишнего писать.

И не надо ничего дробить по 50-100 записей... Сколько есть данных, столько и заливай. Только настрой правильно ключи (индексы). И будет тебе счастье!
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.