За последние 24 часа нас посетили 17550 программистов и 1723 робота. Сейчас ищут 1659 программистов ...

Warning No such file or directory

Тема в разделе "PHP для профи", создана пользователем sphinks, 30 мар 2017.

Метки:
  1. sphinks

    sphinks Активный пользователь

    С нами с:
    30 мар 2017
    Сообщения:
    7
    Симпатии:
    0
    Доброго дня всем. Ситуация:
    На сервер приходят сообщения (до 1000 в секунду) по посту. Я их сохраняю вот так:
    Код (Text):
    1. $xml_post = file_get_contents('php://input');
    2.     // If we receive data, save it. .
    3.     if ($xml_post) {
    4.         $number = 0;
    5.         $xml_file = 'pusherFiles2/received_xml_' . date('Y_m_d-H-i-s') .'_'.$number. '.xml';
    6.         while(file_exists($xml_file)){
    7.             $number++;
    8.             $xml_file = 'pusherFiles2/received_xml_' . date('Y_m_d-H-i-s') .'_'.$number. '.xml';
    9.         }
    10.         $fh = fopen($xml_file, 'w') or die();
    11.         fwrite($fh, $xml_post);
    12.         fclose($fh);}
    Далее мне нужно обработать эти файлы (рассортировать). Так вот я делаю так:
    Код (Text):
    1. $fileList = array_slice(scandir('pusherFiles/'),2,100);
    2. foreach($fileList as $file){
    3.                
    4.                 if(file_exists($oldfolder.$file))rename($oldfolder.$file,$newfolder.$file);
    5.             }
    И иногда получаю ворнинг ПХП Warning: rename(pusherFiles/received_xml_2017_03_30-21-10-21_2.xml,o_temp2/received_xml_2017_03_30-21-10-21_2.xml): No such file or directory in ...

    Что-то не пойму я, ведь стоит проверка перед операцией if(file_exists($oldfolder.$file)). Откуда тогда ворнинг?
    Подобное происходит и с unlink-ом, когда я удаляю Warning: unlink(o_temp3/received_xml_2017_03_30-21-09-28_6.xml)
    вот код:
    Код (Text):
    1. if(file_exists($filename)) unlink($filename);
    Общая картинка такая:
    Код (Text):
    1.  $xml_post = file_get_contents('php://input');
    2.     // If we receive data, save it. .
    3.     if ($xml_post) {
    4.         $number = 0;
    5.         $xml_file = 'pusherFiles2/received_xml_' . date('Y_m_d-H-i-s') .'_'.$number. '.xml';
    6.         while(file_exists($xml_file)){
    7.             $number++;
    8.             $xml_file = 'pusherFiles2/received_xml_' . date('Y_m_d-H-i-s') .'_'.$number. '.xml';
    9.         }
    10.        
    11.         $fh = fopen($xml_file, 'w') or die();
    12.         fwrite($fh, $xml_post);
    13.         fclose($fh);
    14.         $oDecoder = new Controller_Decoder();
    15.         $i=0;
    16.         if(count(array_slice(scandir('pusherFiles2/'),2)) > 500){
    17.             shell_exec("mv pusherFiles2/* pusherFiles");
    18.            
    19.         }
    20.         while(file_exists('oldFiles/process'.$i.'.txt') && $i<4){  
    21.             $i++;
    22.         }
    23.         if($i<4){
    24.         $oDecoder->openProcess($i);
    25.         }
    26.        
    27.        
    28.         return $xml_file;
    29.     }
    30. //functoins from  class Decoder
    31. function openProcess($i){
    32.     $tempdir = 'oldFiles/';
    33.     $tempFile = 'process'.$i.'.txt';
    34.     $oldfolder = 'pusherFiles/';
    35.     $filename = $tempdir.$tempFile;
    36.     $post = 'process'.$i;
    37.     if(!file_exists($filename)){  
    38.         $fh = fopen($filename, 'w') or die();
    39.         fwrite($fh, $post);
    40.         fclose($fh);
    41.         $fileList = array_slice(scandir('pusherFiles/'),2,100);
    42.         if(count($fileList) >0){
    43.             $newfolder = 'o_temp'.$i.'/';
    44.             if (!file_exists($newfolder)) {
    45.                 mkdir($newfolder, 0777, true);
    46.             }
    47.            
    48.             foreach($fileList as $file){
    49.                 if(file_exists($oldfolder.$file))rename($oldfolder.$file,$newfolder.$file);
    50.             }
    51.            
    52.             $listDecode = array_slice(scandir($newfolder),2);
    53.             $res = $this->action_getFilecim($listDecode,$newfolder);
    54.  
    55.         }
    56.         unlink($filename);
    57.     }
    58. }
     
  2. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    В какой строке указан?
    Почему забирается именно как file_get_contents('php://input'), а не просто читается текст из соответствующей POST-переменной?
    Отладку пробовали делать?
     
  3. sphinks

    sphinks Активный пользователь

    С нами с:
    30 мар 2017
    Сообщения:
    7
    Симпатии:
    0
    Да ворнинг указывает именно на те строки, которые я указал.
    Забирается по //input, - так указано было в API и неизвестно имя POST . Данные приходят в json виде. Все, что приходит - в файл, и потом уже разбираю.
    Проблемы начинаются, когда более 100 (иногда до 1000) пакетов в секунду приходят по 1-4 Кб. Я потом эти пакеты в БД запихиваю.
    Меня удивляет сам факт того, что после проверки выскакивают эти сообщения.
    Может кто сталкивался с таким?
    Сейчас временное решение нашел с помощью ассинхронного вызова скрипта + создал буферную папку, куда перекидывает по 100 файлов и потом оттуда растягивается скриптом. И таких ошибок нет.
    Какова вероятность, что в момент проверки файл есть, а после проверки его уже нет?
     
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    https://en.wikipedia.org/wiki/Race_condition
    --- Добавлено ---
    - Доктор, когда я вот так вот делаю, мне вот тут вот больно.
    - Не делайте так.

    Решение тут обычно такое: не писать код, в котором возможен рейс кондишн.

    Ну в твоём случае очевидное решение в лоб - не писать в файл, а сразу разбирать и сохранять под правильным названием.

    Но наверное тебе жутко страшно, что в случае ошибки что-то потеряется. Наверное поэтому ты их в файлы пихаешь. Вообще, мне честно говоря непонятно, почему ты не работаешь с какой-нить mongodb. Но видимо тебе либо лень всё это настраивать, либо ещё чего.

    Поэтому вот тебе ещё один костыль:
    Пишешь первичные файлы в одну папку, а разобранные - в другую. Всё. Победа. А потом кроном раз в час из первой папки стираешь те, что старше суток, например.
     
    sphinks_a нравится это.
  5. sphinks

    sphinks Активный пользователь

    С нами с:
    30 мар 2017
    Сообщения:
    7
    Симпатии:
    0
    Спасибо за советы. Сейчас буду пробовать. О результатах сообщу позднее.
     
  6. sphinks_a

    sphinks_a Активный пользователь

    С нами с:
    17 авг 2011
    Сообщения:
    11
    Симпатии:
    0
    Значит что я пробовал и что получилось.
    0. Во всем виноват оказался Рейс Кондишн.
    1.
    Абзац пришел минут через 5, когда проц разошелся на 500% и просто стал рубить все.
    2.
    Посмотрел на MongoDb. Оказался очень интересный инструмент. Правда я раньше с ним не работал никогда. Но установил, настроил и все, вроде бы, закрутилось.
    3. В виду нехватки времени реализовал костыль: Файлы пишутся в Монгу, оттуда скриптом выбирается json и пишется в базу ΜySql а в Монге удаляются по ИД.
    4. О Монге знаю мало, поэтому буду тестировать ее на выборку и апдейт данных. Посмотрим, как она себя поведет по времени. Но точно понятно, что на запись она быстрее, чем МайСиКУеЛ. Даже просто запись в файл давала сбой и были битые пакеты (нарушена json кодировка).
    Как и ожидалось, самое узкое место - операции с БД.
    Большое спасибо за направления. Пойду совершенствоваться.
    Спасибо всем!
     
  7. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    если тебе не надо всё-всё гарантированно на 100% сохранять, то можно заюзать кеши типа memcached или apc или redis. Но они могут переполниться, если не будешь успевать разбирать, а сбрасывать на диск они не будут. Редис умеет, но мемкеш или апц это чисто кеш в оперативке

    больше похоже, что тебе надо с одного сервера пихать в редис отдельно стоящий, допустим. А с третьего - разбирать то, что накидалось в редис.
     
  8. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    @sphinks я бы на твоем месте давал файлам имена из uniqid(). Ведь всё портит, насколько я понял, $number.
     
  9. sphinks_a

    sphinks_a Активный пользователь

    С нами с:
    17 авг 2011
    Сообщения:
    11
    Симпатии:
    0
  10. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ну медленно понятие относительное. расскажи, как именно ты его дрючишь. Может ты это неправильно делаешь.
    --- Добавлено ---
    а попробуй-ка вместо INSERT писать INSERT DELAYED
     
  11. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    В случае рэйс кондишен всегда будет портить самое медленное звено. Теперь вместо MySQL будет что-то другое, но реже.
     
  12. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    не, надо разнести так, чтобы рейса не было вообще. Нужно, чтобы один складывал, а другой разбирал.
     
    denis01 нравится это.
  13. sphinks_a

    sphinks_a Активный пользователь

    С нами с:
    17 авг 2011
    Сообщения:
    11
    Симпатии:
    0
    Медленно - это 2500 строк за 3 минуты.
    У меня задача такая:
    1. Приходящие пакеты (1-8 КБ) в формате json от провайдера инфы помещать в базу, которую использует сайт.
    2. Потом я Ajax-ом на сайте обновляю инфу.

    Но, чтоб поместить их в базу, нужно их сортировать.
    json вида
    Код (Text):
    1. {
    2.   "Header": {
    3.     "ModuleId": 3,
    4.     "GeneratedTime": "2017-03-31T17:24:29.5822999Z",
    5.     "MsgGuid": "bfd5d9d6-a6fa-414f-903b-e09300d433a9",
    6.     "MsgId": 592
    7.   },
    8.   "Peer": {
    9.     "Id": 2274581,
    10.     "Events": {
    11.       "Event": {
    12.         "Id": 6,
    13.         "Name": "Birthday",
    14.         "Guests": [
    15.           {
    16.             "Name": "Ivan",
    17.             "SecondName": "Kolomiec",
    18.             "Phone": "+30xxxxx",
    19.             "Status": "Active"
    20.           },
    21.          {
    22.             "Name": "Petro",
    23.             "SecondName": "Volovec",
    24.             "Phone": "+30xxxxx",
    25.             "Status": "Active"
    26.           },
    27.          {
    28.             "Name": "Maxim",
    29.             "SecondName": "Kopernic",
    30.             "Phone": "+30xxxxx",
    31.             "Status": "Active"
    32.           }]
    33.         }
    34.     }
    35.   }
    36. }
    Должен быть отсортирован по ИД Пира. (таблица в MySQL Peers) peer_id, peer_info, peer_timeinsert, по Event для Peer ( таблица Events) event_id, event_name. И т.к. у меня нет ИД для Guests, то я создал таблицу Guests, где сохраняю гостей с ИД. (guest_id [autoincr], guest_name, guest_event_id . И таблица GEvents, где хранятся все guests для каждого Event : gevent_id (autoinc), gevent_peer_id, gevent_event_id, gevent_name, gevent_guest_id, gevent_guest_name, gevent_guest_status
    Обработка пакета происходит так:
    1. Смотрю Header -> ModuleId. (Значения 1-10)
    2. Если Header -> ModuleId=1 -> Там будет информация только о Peer-e. Беру Peer Id. Запрос в таб Peers. Если нет такого Id, то записываю, если есть - обновляю.
    2. Если Header -> ModuleId=2. Тогда Информация о Event и Guests.
    2.1 Запрос в БД в Peers, SELECT peer_id FROM peers WHERE peer_id = [peer_id] Если нет результата, - закончили процедуру.
    2.2 Если есть, запрос SELECT * FROM events WHERE event_id = [event_id]. Если нет -> вставляем Event
    2.3 Если есть, запрос в БД SELECT guest_id, guest_name FROM guests WHERE guest_event_id = [event_id] и запоминаю в массиве. Благо тут максимум к одному Event прикреплено не больше 30 guests. Но Event ов около 300.
    2.4 Начинаю цикл foreach($guest as $guest):
    2.4.0 Нахожу guest_id из массива, где есть совпадения с $guest[name]. Если нет совпадений, вставляю Guest в таблицу Guests и выбираю ИД вставленного​
    2.4.1 Смотрю в GEvents, есть ли у нас такая запись: SELECT gevent_id FROM gevents WHERE gevent_peer_id =[peer_id] AND gevent_event_id = [event_id] AND gevent_guest_name =[guest_name].
    2.4.2 Если нет, то вставляю новую запись
    2.4.3 Если есть, то делаю Update по gevent_id.​
    2.5 Конец цикла.
    2.6 Конец обработки.​
    Думаю, проще уже некуда.
    Во всех таблицах Primary_KEY по Id.
    Ну и Хедеры я сортирую с помощью SWITCH, где для каждого вызывается своя функция сортировки.
     
    #13 sphinks_a, 1 апр 2017
    Последнее редактирование: 1 апр 2017
  14. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    обычно как раз база сортирует всё.

    это делается иначе. смотри синтаксис insert ... on duplicate key update

    я не понял, ты что, херачишь запросы в цикле?
    --- Добавлено ---
    покажи код
     
  15. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    какая разница для реляционной БД, в каком порядке записаны строки? Всегда можно сделать индекс на нужное поле.
     
  16. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Код! Код! Код!
     
  17. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    С этой штукой надо быть аккуратным. Она сразу возвращает успешный ответ от базы. Если при этом, при вставке, ты не можешь гарантировать 100% успех, мало ли, по какой причине, то ты будешь с некоторой вероятностью просирать строки, которые, в противном случае, можно было бы хотя бы пометить в логе как пофейлившиеся.

    Я щас еще дальше шагну, зацени.
    Автор, опиши изначальную проблему, которую пытаешься решать, а не то, как ты видишь ее решение. Тут какой-то очень специфичный кейс, и есть вероятность, что это "проблема X-Y".
     
  18. sphinks_a

    sphinks_a Активный пользователь

    С нами с:
    17 авг 2011
    Сообщения:
    11
    Симпатии:
    0
    Вот код самой грузоподъемной функции.
    PHP:
    1. public function analyzeEvent($fullData){
    2. //    Debug('Start AnalyzeOdd at:'.time());
    3.     $result['result'] = 0;
    4.     $result['msg'] = '';
    5.     $result['error'] = '';
    6.     $result_event = array();
    7.     $peer = $fullData['Peer'];
    8.     $module = $fullData['Header']['ModuleId'];
    9.     $data = array('peer_id'=>$peer['Id']);
    10.     $gevent_peer_id = $peer['Id'];
    11.     $table = 'peers';
    12.     $ev = $this->evExists($data,$table); // проверяет, существует ли Пир
    13.     if(!empty($ev)){ // peer found
    14. //        Debug(' Found Ev:'.$ev['peer_id'].' at'.time());
    15.         $outcome = $fullData['Peer']['Events']['Event'];
    16. //        $result['msg'] .= ' Found Ev:'.$ev['peer_id'];
    17.         $data=array('event_id'=>$outcome['Id']);
    18.         $event = $this->evExists($data,'events');
    19.         if(empty($event)){ // event not found
    20.             $newEv = $this->insertEv($outcome);
    21.             if(empty($newEv)){ // cannot insert BType
    22.                 $result['result'] = 0;
    23.                 $result['error'] = 'Cannot insert Event '.$outcome['Id'].':'.$outcome['Name'];
    24.                 return $result;
    25.             }
    26.         }
    27.         $gevent_event_id = $outcome['Id'];
    28.         $cond_guests = array('guest_event_id = '.$outcome['Id']);
    29.         $guests = $this->model->getAllData('guests',$cond_guests);
    30. //        Debug($guests);
    31.         foreach($outcome['Guests'] as $guesten){
    32.             $gevent_name_name = $this->replaceT($guesten['Name']);
    33.             $adds = array_key_exists('Phone',$guesten)?$this->replaceT($guesten['Phone']):'';
    34.             $conditions = array(
    35.                 'gevent_peer_id'=>$gevent_peer_id,
    36.                 'gevent_event_id'=>$gevent_event_id,
    37.                 'gevent_name_name'=>$gevent_name_name,
    38.                 'gevent_adds'=>$adds,
    39.                 'gevent_type'=>$module
    40.             );
    41.             $gevent = $this->evExists($conditions,'gevents');
    42.             if(empty($gevent)){ // not found gevent need insert
    43.                 //Debug('Not Found Guest:'.' at'.time());
    44.                 //Debug($conditions);
    45.                 $found = -1;
    46.                 if(!empty($guests)){
    47.                     foreach($guests as $guest){
    48.                         if($guest['guest_name'] == $this->replaceT($guesten['Name'])){
    49.                             $found = $guest['guest_id'];
    50.                         }
    51.                     }
    52.                 }
    53.                 if($found == -1){ // not found guest
    54.                     $newGuest = $this->insertGuest($outcome['Id'],$guesten);
    55.                     if(empty($newGuest)){ // cannot insert guest
    56.                         $result['result'] = 0;
    57.                         $result['error'] = 'Cannot insert guest '.$guesten['Name'].', Event:'.$outcome['Name'];
    58.                         return $result;
    59.                     }else{
    60.                         $data=array('guest_event_id' =>$outcome['Id'],'guest_name'=>$guesten['Name']);
    61.                         $guestArr = $this->evExists($data,'guests');
    62.                         $guest_id = $guestArr['guest_id'];
    63.                     }
    64.                 }else{
    65.                     $guest_id = $found;
    66.                 }
    67.                 $input['gevent_peer_id'] = $peer['Id'];
    68.                 $input['gevent_event_id'] = $outcome['Id'];
    69.                 $input['gevent_event_name'] =  $this->replaceT($outcome['Name']);
    70.                 $input['gevent_guest_id'] = $guest_id;
    71.                 $input['gevent_name_name'] =  $this->replaceT($guesten['Name']);
    72.                 $input['gevent_adds'] = $adds;
    73.                 $input['gevent_phone'] = $guesten['Phone'];
    74.                 $input['gevent_status'] = $guesten['Status'];
    75.                 $input['gevent_type'] = $module;
    76.                 $newGevent = $this->model->insert($input,'gevents');
    77.                 if(empty($newGevent)){ // cannot insert gevent
    78.                     $result_ins[$events['Id']]['result'] = 0;
    79.                     $result_ins[$events['Id']]['error'] = 'Cannot insert gevent ';
    80.                 }else{
    81.                     $result_ins[$events['Id']]['result'] = 1;
    82.                     $result_ins[$events['Id']]['msg'] = 'Insert gevent successfull';
    83.                 }
    84.             }else{ // gevent found
    85.                 $input['gevent_phone'] = $guesten['Phone'];
    86.                 $input['gevent_status'] = $guesten['Status'];
    87.                 $cond = array('gevent_id = '.$gevent['gevent_id']);
    88.                 $update = $this->model->update($cond,$input,'gevents',$this->connDb);
    89.                 if(empty($update)){ // not update Gevent
    90.                     $result_ins[$gevent['gevent_id']]['result'] = 0;
    91.                     $result_ins[$events['Id']]['error'] = 'Cannot Update gevent:'.$gevent['gevent_id'];
    92.                 }else{ // updated
    93.                     $result_ins[$gevent['gevent_id']]['result'] = 1;
    94.                 }
    95.             }
    96.         }
    97.     }else{ // peer not found
    98.         $result['result'] = 1;
    99.         $result['error'] = 'Not found Peer ';
    100.     }
    101.     if(!empty($result_ins)){
    102.         $result['result']=1;
    103.         foreach($result_ins as $key=>$value){
    104.             if($value['result'] == 0){
    105.                 $result['error'] .= $value['error'];
    106.                 $result['result'] = 0;
    107.             }
    108.         }
    109.     }else{
    110.         $result['error'] .= 'No insert or Update';
    111.     }
    112.     return $result;
    113. }
    Задача, которую пытаюсь решить.
    Приходят на сервер пакеты (до 1000 в секунду) с актуальными данными в формате json. Есть 10 Модулей - 10 разных вариантов данных. Когда приходит пакет, нужно сравнить, есть ли в базе данные о нем. Если есть, то обновить, если нет, то вставить. Как -то так.
    Сортировать, имеется ввиду данные, какие в какие таблицы совать.
    Ну да. Я ж тут проверяю соответствие каждого ко множеству, получается
     
  19. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    Сравнивание идет по какому признаку? По некоему идентификатору? Для сравнивания ты сначала вытаскиваешь из БД значение, потом проверяешь, потом кладешь обратно?

    В таком случае ответ тебе уже был дан:
    И ничего не надо проверять. Просто отдавай базе на запись, она сама разберется. У тебя же всего два кейса - если нет данных, то создать, если есть, то обновить. Точка. Вытаскивать и проверять что-то руками нет смысла.

    Ты можешь накапливать запросы и отдавать их пачкой. Погляди синтаксис множетвенной вставки. Можно за один присест отдать базе хоть тыщщу строк. И работать оно будет чуть ли не в тыщщу раз быстрее, чем тыщща раз по разу.
     
    sphinks_a нравится это.
  20. sphinks_a

    sphinks_a Активный пользователь

    С нами с:
    17 авг 2011
    Сообщения:
    11
    Симпатии:
    0
    Спасибо. Сейчас буду мат. часть смотреть.
     
  21. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ты можешь копить айдишники, и одним запросом их все вытаскивать. См where id in (1, 2, 3)
     
  22. sphinks

    sphinks Активный пользователь

    С нами с:
    30 мар 2017
    Сообщения:
    7
    Симпатии:
    0
    В общем, я тут подумал, потестировал все и сделал такой вывод:
    1. Нужен сервер помощней.
    2. Входные данные записываю в МонгуДБ в разные коллекции, исходя из заголовков.
    3. В этих коллекция раз в 5 минут делается чистка: выбираются записи и сортируются в МайэСКуэЛ (некоторые) и в "Архив". Таким образом в коллекциях сохраняются только актуальные данные и новые.
    4. на сайте отображаются данные из коллекций. Если кто-то хочет посмотреть статистику за прошлые периоды, тогда достаем из архива.
    5. МySQL использовать для технических нужд сайта, где нужны зависимости.
    Уже 4 дня тест проходит хорошо. Сервер не перегружен, все довольны.
    Всем спасибо за участие.
     
  23. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    круто!
     
  24. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    До 1000 это 10?
     
  25. Abyss

    Abyss Старожил

    С нами с:
    12 дек 2015
    Сообщения:
    1.298
    Симпатии:
    218
    Адрес:
    Default city
    Я чет всё прочитал и так и не понял в чем затык. Написать код, который будет принимать любой пакет и приводить его к общему виду, если присутствуют уникальные идентификаторы, то это изи, если нет, то вычленить за что можно зацепится, на крайняк добавить module_id. Унифицированные данные в массив массивов и построить запрос INSERT INTO ON DUPLICATE KEY UPDATE (один запрос!).