简体   繁体   English

具有数千个插入的Codeigniter的insert_batch()缺少记录

[英]Codeigniter's insert_batch() with thousands of inserts has missing records

I'm using insert_batch() to mass insert 10000+ rows into a table in a database. 我正在使用insert_batch()insert_batch()行大量插入到数据库的表中。 I'm making some tests and I have noticed that sometimes all the 10.000+ rows are getting inserted correctly but in some occasions I miss 100+ rows in my table's total count. 我正在进行一些测试,我注意到有时所有10.000多行都被正确插入,但在某些情况下,我会错过表格总数中的100多行。

The field data in the records I have are ok as I'm using the same data for each of my tests and most of the times I have no problem. 我所拥有的记录中的字段数据是可以的,因为我为每个测试使用相同的数据,而且大多数时候我都没有问题。 For example I tried 20 times to insert the same data into my database and at 19 times all rows will be inserted correctly but in this one time I will miss 100 or maybe more rows. 例如,我尝试了20次将相同的数据插入到我的数据库中,并且19次所有行都将正确插入,但在这一次我将错过100行或更多行。

The function for the insert_batch() follows: insert_batch()的函数如下:

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
    }
}

How can I debug insert_batch() for such an occasion? 如何在这样的场合调试insert_batch()

I have made some changes on the DB_active_rec.php to do some logging during the insert_batch and so far I can't successfully reproduce the problem to see what is going wrong. 我在DB_active_rec.php上做了一些更改,以便在DB_active_rec.php期间进行一些日志记录,到目前为止,我无法成功重现问题以查看出现了什么问题。 But as far as the problem appeared 2-3 times at the beginning and I did not major changes to my logic to fix it, I can't leave it like this as I don't trust codeigniter's insert_batch() function for production. 但是,就问题在开始时出现2-3次并且我没有对我的逻辑进行重大修改来修复它时,我不能这样做,因为我不相信codeigniter的insert_batch()函数用于生产。

I'm also adding codeigniter's insert_batch() function: 我还添加了codeigniter的insert_batch()函数:

    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;
}

The last log_message() with the total inserts from batch also shows the problem as when I have less inserts than expected I get the non-expected number of inserts there as well. 带有批量插入总数的最后一个log_message()也显示了问题,因为当插入的插入量少于预期时,我也得到了非预期的插入数量。

I have to think something else for inserting thousands of rows into my database w/ or w/o codeigniter. 我不得不考虑将数千行插入我的数据库w /或不使用codeigniter。

anyone has any clue for this kind of problem? 有谁对这类问题有任何线索? Maybe it has something to do with the hard drive or the memory of the system during to lack of performance? 也许它与硬盘驱动器或系统内存有关,在性能不足的情况下? It's an old PC with 1gb of ram. 这是一台带有1GB内存的旧PC。

EDIT: As requested I'm putting here an example INSERT statement with 9 rows that is being produced by codeigniter's insert_batch() function 编辑:根据要求,我在这里放一个示例INSERT语句,其中包含9行,由codeigniter的insert_batch()函数生成

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)

That was a completed insert. 那是一个完整的插页。

insert_batch() tries to avoid exactly your problem - trying to insert data larger than MySQL is configured to process at a time. insert_batch()试图完全避免你的问题 - 尝试插入大于MySQL的数据被配置为一次处理。 I'm not sure if MySQL's option for that was max_allowed_packet or something else, but the problem with it is that it sets a limit in bytes and not a number of rows. 我不确定MySQL的选项是否是max_allowed_packet或其他东西,但问题是它设置了一个字节限制而不是多行。

If you'll be editing DB_active_rec.php, mysql_driver.php or whatever appropriate ... try changing that 100 count in the for() loop. 如果您要编辑DB_active_rec.php,mysql_driver.php或任何适当的...尝试在for()循环中更改那100个计数。 50 should be a safer choice. 50应该是一个更安全的选择。

Other than that, FYI - affected_rows() won't return the correct value if you're inserting more than 100 rows via insert_batch() , so it's not reliable to use it as a success/error check. 除此之外,如果您通过insert_batch()插入超过100行,FYI - affected_rows()将不会返回正确的值,因此将其用作成功/错误检查是不可靠的。 That's because insert_batch() inserts your data by 100 records at a time, while affected_rows() would only return data for the last query. 这是因为insert_batch()将数据插入100条记录,而affected_rows()只返回上次查询的数据。

The solution of this problem is, you need to go in directory /system/database/ and open file DB_query_builder.php and update 解决这个问题的方法是,你需要进入目录/system/database/并打开文件DB_query_builder.php并更新

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

you can set the size of your requirement. 您可以设置您的要求的大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM