2013-08-02 15 views
6

Używam insert_batch() do wstawienia w masie ponad 10000 wierszy do tabeli w bazie danych. Robię kilka testów i zauważyłem, że czasami wszystkie 10.000 wierszy są poprawnie wstawiane, ale w niektórych przypadkach brakuje mi ponad 100 wierszy w całkowitej liczbie moich tabel.Moduł insert_batch() z tysiącami wstawek Codeigniter ma brakujące rekordy

Dane pola w rekordach, które posiadam są w porządku, ponieważ korzystam z tych samych danych dla każdego z moich testów i większość czasu nie mam problemu. Na przykład próbowałem 20 razy, aby wstawić te same dane do mojej bazy danych i w 19 razy wszystkie wiersze zostaną wstawione poprawnie, ale w tym jednym czasie będę tęsknił za 100 lub może więcej wierszy.

Funkcja dla insert_batch() następująco:

protected function save_sms_to_database() { 
    //insert_Batch 
    $datestring = "%Y-%m-%d %h:%m:%s"; 
    $time = time(); 
    $datetime = mdate($datestring, $time); 

    $this->date_sent = $datetime; 

    foreach ($this->destinations as $k => $v) { 
     $sms_data[$k] = array(
      'campaign_id' => $this->campaign_id, 
      'sender_id' => $this->from, 
      'destination' => $v, 
      'token' => md5(time() . 'smstoken' . rand(1, 99999999999)), 
      'message' => $this->body, 
      'unicode' => $this->unicode, 
      'long' => $this->longsms, 
      'credit_cost' => $this->eachMsgCreditCost, 
      'date_sent' => $this->date_sent, 
      'deleted' => 0, 
      'status' => 1, 
      'scheduled' => $this->scheduled, 
     ); 
    } 

    $this->ci->db->insert_batch('outgoingSMS', $sms_data); 
    if ($this->ci->db->affected_rows() > 0) { 
     // outgoingSMS data were successfully inserted  
     return TRUE; 
    } else { 
     log_message('error', $this->campaign_id.' :: Could not insert sms into database'); 
     log_message('error', $this->ci->db->_error_message()); 
     return FALSE; // sms was not inserted correctly 
    } 
} 

Jak można debugować insert_batch() na taką okazję?

Dokonałem pewnych zmian na DB_active_rec.php, aby wykonać pewne logowanie podczas operacji wstawiania i jak dotąd nie udało mi się odtworzyć problemu, aby zobaczyć, co się dzieje. Ale o ile problem pojawił się 2-3 razy na początku i nie wprowadziłem większych zmian w mojej logice, aby to naprawić, nie mogę tego tak zostawić, ponieważ nie ufam funkcji codeigniter dla insert_batch() produkcji.

Jestem również dodanie insert_batch CodeIgniter za() funkcja:

public function insert_batch($table = '', $set = NULL) 
{ 
     $countz = 0; 
    if (! is_null($set)) 
    { 
     $this->set_insert_batch($set); 
    } 

    if (count($this->ar_set) == 0) 
    { 
     if ($this->db_debug) 
     { 
      //No valid data array. Folds in cases where keys and values did not match up 
      return $this->display_error('db_must_use_set'); 
     } 
     return FALSE; 
    } 

    if ($table == '') 
    { 
     if (! isset($this->ar_from[0])) 
     { 
      if ($this->db_debug) 
      { 
       return $this->display_error('db_must_set_table'); 
      } 
      return FALSE; 
     } 

     $table = $this->ar_from[0]; 
    } 

    // Batch this baby 
    for ($i = 0, $total = count($this->ar_set); $i < $total; $i = $i + 100) 
    { 

     $sql = $this->_insert_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_keys, array_slice($this->ar_set, $i, 100)); 

     //echo $sql; 

     $this->query($sql); 
        $countz = $countz + $this->affected_rows(); 
    } 

    $this->_reset_write(); 
      log_message('info', "Total inserts from batch:".$countz); 

    return TRUE; 
} 

Ostatni log_message() z całkowitych wstawkami z partii pokazuje również problem, ponieważ kiedy mają mniej wkładek niż oczekiwano uzyskać non-spodziewaną liczbę tam również wstawek.

Muszę wymyślić coś innego, aby wstawić tysiące wierszy do mojej bazy danych w/lub bez sygnatury.

ktoś ma jakąkolwiek wskazówkę dotyczącą tego rodzaju problemu? Może ma to coś wspólnego z dyskiem twardym lub pamięcią systemu podczas braku wydajności? To stary komputer z 1GB pamięci RAM.

EDIT: Zgodnie z wnioskiem Kładę tu oświadczenie przykład INSERT z 9 wierszy, które jest wytwarzane przez CodeIgniter za insert_batch() funkcji

INSERT INTO `outgoingSMS` (`campaign_id`, `credit_cost`, `date_sent`, `deleted`, `destination`, `long`, `message`, `scheduled`, `sender_id`, `status`, `token`, `unicode`) VALUES ('279',1,'2013-08-02 02:08:34',0,'14141415151515',0,'fd',0,'sotos',1,'4d270f6cc2fb32fb47f81e8e15412a36',0), ('279',1,'2013-08-02 02:08:34',0,'30697000000140',0,'fd',0,'sotos',1,'9d5a0572f5bb2807e33571c3cbf8bd09',0), ('279',1,'2013-08-02 02:08:34',0,'30697000000142',0,'fd',0,'sotos',1,'ab99174d88f7d19850fde010a1518854',0), ('279',1,'2013-08-02 02:08:34',0,'30697000000147',0,'fd',0,'sotos',1,'95c48b96397b21ddbe17ad8ed026221e',0), ('279',1,'2013-08-02 02:08:34',0,'306972233469',0,'fd',0,'sotos',1,'6c55bc3181be50d8a99f0ddba1e783bf',0), ('279',1,'2013-08-02 02:08:34',0,'306972233470',0,'fd',0,'sotos',1,'d9cae1cbe7eaecb9c0726dce5f872e1c',0), ('279',1,'2013-08-02 02:08:34',0,'306972233474',0,'fd',0,'sotos',1,'579c34fa7778ac2e329afe894339a43d',0), ('279',1,'2013-08-02 02:08:34',0,'306972233475',0,'fd',0,'sotos',1,'77d68c23422bb11558cf6fa9718b73d2',0), ('279',1,'2013-08-02 02:08:34',0,'30697444333',0,'fd',0,'sotos',1,'a7fd63b8b053b04bc9f83dcd4cf1df55',0) 

To była zakończona wkładka.

+0

W tym przypadku sugerowałbym wstawić rekordy w pętli zamiast pojedynczego zapytania '(insert_batch)'. W ten sposób możesz również debugować swoje zapytania. –

+0

Czy możesz pokazać nam zapytania SQL, które są uruchamiane? Może niektóre są zniekształcone? Czy rozważałeś użycie masy instrukcji 'INSERT'? – Halcyon

+0

@NiloySaha Nie mogę używać pętli dla tak dużej ilości wstawek, ponieważ obniży to wydajność mojego systemu. Szczególnie w produkcji będzie to katastrofalne. Kiedy użyłem pętli podczas opracowywania wkładek, nie miałem problemów z tego co pamiętam, ale nie mogę użyć tej logiki do tak dużej ilości wstawek. – sotoz

Odpowiedz

3

insert_batch() próbuje uniknąć twojego problemu - próbując wstawić dane większe niż MySQL jest skonfigurowane do przetwarzania na raz. Nie jestem pewien, czy opcja MySQL do tego była max_allowed_packet czy coś innego, ale problem polega na tym, że ustawia limit w bajtach, a nie w liczbie wierszy.

Jeśli będziesz edytować DB_active_rec.php, mysql_driver.php lub cokolwiek odpowiedniego ... spróbuj zmienić tę liczbę 100 w pętli for(). 50 powinno być bezpieczniejszym wyborem.

Poza tym, FYI - affected_rows() nie zwróci poprawnej wartości, jeśli wstawiasz więcej niż 100 wierszy przez insert_batch(), więc nie można jej używać jako sprawdzianu powodzenia/błędu. To dlatego, że insert_batch() wstawia dane przez 100 rekordów na raz, podczas gdy affected_rows() będzie zwracał dane tylko dla ostatniego zapytania.

+0

dziękuję za odpowiedź, dla 'affected_rows()' jeśli zobaczysz zmiany, które wprowadziłem do 'DB_active_rec.php', udało mi się policzyć dokładnie ile wstawek zostało zrobionych z insert_batch, a całkowita liczba, którą otrzymuję, jest zawsze właściwa (ponieważ mogę to również zweryfikować za pomocą 'select count (*)'). Spróbuję zmienić liczbę pętli, jak powiedziałeś, i zrobić tam kilka testów. Jeśli wszystko pójdzie dobrze, przyjmuję twoją odpowiedź :) – sotoz

+0

Czy możesz podzielić się z nami tym, jak poradziłeś sobie z tym problemem? – siva

0

Rozwiązaniem tego problemu jest, trzeba iść w katalogu /system/database/ i otwartego pliku DB_query_builder.php i aktualizować

public function insert_batch($table, $set = NULL, $escape = NULL, $batch_size = 1000)

można ustawić wielkość zapotrzebowania.

Powiązane problemy