1

I installed fork on my Ubuntu Server (using PHP-Apache-Codeigniter).

I have this code:

<?php 

public function add_keyword() {

    $keyword_p = $this->input->post('key_word');

    $prod      = $this->input->post('prod_name');
    $prod      = $this->kas_model->search_prod_name($prod);
    $prod      = $prod[0]->prod_id;

    $country   = $this->input->post('key_country');

    $keyword = explode(", ", $keyword_p);
    var_dump($keyword); 
    $keyword_count = count($keyword);
    echo "the keyword count: $keyword_count";

    // Create   fork
    $pid = pcntl_fork();
    if(!$pid){

        for ($i=0; $i < $keyword_count ; $i++) { 

            // Inserts the inputs to the "keywords" table
            $this->kas_model->insert_keyword($keyword[$i], $prod, $country);

            // Gets relevant IDs for the inserted prod and keyword
            $last_inserted_key = $this->kas_model->get_last_rec('keywords');
            $keyword_id        = $last_inserted_key[0]->key_id;
            $prod_id           = $last_inserted_key[0]->key_prod;
            $prod_id_query     = $this->kas_model->get_prod_row_by_id($prod_id);
            $prod_id_a  = $prod_id_query[0]->prod_a_id;
            $prod_id_b  = $prod_id_query[0]->prod_b_id; 

            // Run the keyword query (on API) for today on each one of the keys and insert to DB aslong that the ID isn't 0.  
            if ( ($prod_id_a != 0) || ( !empty($prod_id_a) ) ) {
                $a_tdr = $this->get_var1_a_by_id_and_kw( $prod_id_a, $keyword[$i], $country);
            } else {
                $a_tdr['var1'] = 0;
                $a_tdr['var2'] = 0;
                $a_tdr['var3'] = 0;
            }

            if ( ($prod_id_b != 0) || ( !empty($prod_id_b) ) ) {
                $b_tdr = $this->get_var1_b_by_id_and_kw($prod_id_b, $keyword[$i], $country);
            } else {
                $b_tdr['var1'] = 0;
                $b_tdr['var2'] = 0;
                $b_tdr['var3'] = 0;     
            }

            $this->kas_model->insert_new_key_to_db($keyword_id, $a_tdr['var1'], $b_tdr['var1'], $a_tdr['var2'], $b_tdr['var2'], $a_tdr['var3'], $b_tdr['var3']);

        }
        exit($i);
    }


    redirect('main/kas'); 
}

What the function does: This function gets 1 or more keyword/s, a country var, and a product ID, and runs a query on an external slow API getting variables (runs other functions from within that same controller), and adds them to the database.

Solution: When running this function, and if I insert a lot of keywords, the page loads, and loads, and loads, for a long time, until it's done, and only then - I can continue browsing my website. So I was told to fork it since it's just sending a request to process it in the background, so whenever clicking the submit button, I get redirected to "main/kas".

Currently: I get the my MySQL connection disconnected with this error:

MySQL server has gone away

But with inserting 1 var from all the process.

What I trird till now: As said in this comment: http://www.php.net/manual/en/function.pcntl-fork.php#70721

I have to reconnect to my DB in the parent, and that should solve the problem. I have found this post from 2009 too: Sudden "MySQL server has gone away" error in PHP site

So I continued my "if" with this:

// parent    
} else if ( $pid ) {
        $this->load->database(); 
        $this->db->reconnect();
    }

I tried adding this in the end of the child too (frustration) and in all sorts of variations (regular $link = mysqli_connect("127.0.0.1", "my_user", "my_password", "my_db");) - no success.

Even tried using only $this->load->database(); or only $this->db->reconnect();.

What is the solution for this, this is so frustrating :'(

Community
  • 1
  • 1
Imnotapotato
  • 5,308
  • 13
  • 80
  • 147
  • When you fork, you don't keep the same resources in child process (sockets are perfect example of that). You need to establish a completely new database connection in your code. No reconnect, no load, a fresh new connection. Now, the other question is - why fork at all? It looks like you're using a nuclear bomb to kill a mosquito. You need to determine why insert is slow (likely reason: you are I/O bound). I'd suggest wrapping your inserts with a transaction, instead of issuing one by one. That will remove the need for fork (fork won't help you anyway, it will still be slow). – Mjh Apr 21 '16 at 10:57
  • I'm not sure if I understand you right. You mean, instead of inserting on the fly - it's better to keep the data in an array (for example) and in the end add all to the at once - which will prevent me from waiting for the slow process? – Imnotapotato Apr 21 '16 at 11:21
  • No, what I meant is that even if you fork, the forked process will perform slowly. Your goal is to reduce the amount of time spent waiting to insert into MySQL. This is done by wrapping insert queries into a transaction block - this lets MySQL use 1 input-output operation of the hard drive to write a lot of data, instead of using 1 input-output operation per single query. This way you don't even have to worry about forking and cleaning up afterwards. There's an alternative approach, but it involves `php-fpm` and from what I can tell, you're using Apache with `mod_php` so it's not applicable. – Mjh Apr 21 '16 at 14:49

0 Answers0