【问题标题】:PHP PDO - doesnt insert all statements in the loopPHP PDO - 不在循环中插入所有语句
【发布时间】:2013-07-31 18:11:50
【问题描述】:

让我们想象一下我们应该使用 PDO 在循环中插入大量行的情况。

$sql = "INSERT INTO products (name, price) VALUES (:name, :price)";
$stmt = $db->prepare($sql);

for ($i = 0; $i < 100; $i++)
{
    $name = md5(rand(0, 1000));
    $price = rand(0, 1000);

    $stmt->bindParam(':name', $name);
    $stmt->bindParam(':price', $price);

    try
    {
        $result = $stmt->execute();

        if (!$result)
        {

            print_r($db->errorInfo());
        }

        echo $db->lastInsertId();
    }
    catch (Exception $e)
    {
        echo $e->getMessage();
    }
}

这样,所有 100 行都不会插入到数据库中。第 23 行的 echo 将输出如下内容:

1 2 3 4 5 ... 59 60 61 61 61 61 61 61

第 20 行的 print_r 将输出

 Array (
     [0] => 00000
     [1] => 
     [2] =>  
 )

PDO 错误代码 00000 表示一切正常。并且没有行受到影响。如果我尝试手动插入 $result 为假的行 - 一切正常。

只有 61 行将插入到表中。而且每次运行脚本时,这个数字都会发生变化,这真的很奇怪

为什么?

换一种方式——我们可以从所有插入查询中进行一个查询,并且将插入所有 100 行。这是一个link 粘贴代码。

这是一个表结构:

CREATE TABLE IF NOT EXISTS `products` (
`id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `price` int(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

顺便说一句。我使用带有 HandlerSocker 插件的 percona MySQL 服务器 (5.5)。 我尝试使用 HandlerSocket 插入行。这是一个代码

$hs = new \HSPHP\WriteSocket();
$hs->connect();

$id = $hs->getIndexId('test','products','','name,price');
$loops_number = 10000;

for ($i = 0; $i < $loops_number; $i++)
{
    $name = 'handler-'.md5(rand(0, 1000));
    $price = rand(0, 1000);

    $hs->insert($id, array($name, $price));
}

然后我在这之后 - 我在 DB 中有 ~ 14000 行。为什么?另外,如果我更改循环数(变量 $loops_number) -

if 10 loops - I have 100 rows in DB table
if 50 loops - 50 rows
if 100 loops - 100 rows
if 500 loops - 500 rows
if 1000 loops - ~1100 rows and this number always change. (if I truncate table and run script again)

我的 MySQL 服务器似乎有问题?

【问题讨论】:

  • 重复 61 可能有多种原因。这将有助于发布您的实际代码。这不是,对吗?
  • 您只需要在循环之前准备一次语句。无需准备 100 次 :)
  • 你的意思是一直卡在61?
  • 另外我相信如果你捕捉到 PDOException,你可以通过 errorInfo 获得更具体的错误信息...
  • 关于循环外准备 - 我知道,但这不会解决问题。

标签: php loops pdo percona handlersocket


【解决方案1】:

哇!!!有很多信息要看兄弟。我不确定我的问题是否正确,但如果我有,那么下面的代码只会更好地达到相同的效果:

$name = md5(rand(0, 1000));
$price = rand(0, 1000);

try{

    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    for($i=0, $i<100, $i++){

        $sql = "INSERT INTO products (name, price) VALUES (:name, :price)";
        $stmt = $db->prepare($sql);
        $stmt->execute(array(':name'=>$name[$i], ':price'=>$price[$i]));

        echo $db->lastInsertId();

    }

}catch(PDOException $e){


    print_r($db->errorInfo());

    echo 'An error occured'.$e->getMessage();

} 

试一试,告诉我你得到了什么。

【讨论】:

  • 失败时我得到了这个:Array ( [0] =&gt; 00000 [1] =&gt; [2] =&gt; ) An error occuredSQLSTATE[HY000]: General error: 2013 Lost connection to MySQL server during query
  • 顺便说一句。如果我运行脚本表单浏览器 - 失败。如果表单控制台 - 一切正常。我想 nginx + php-fpm 有问题?
  • 是所有必要的还是项目要求?
  • 没有。我只是玩 percona mysql 服务器,发现这个很旧。所以我想解决问题并回答“为什么会磨损”这个问题:)
  • 如果您的脚本运行良好,请点赞。但是,您还应该考虑其他的做事方式,它们可能会产生相同的结果,但不那么繁琐,效率更高。它的编程之美;)
【解决方案2】:

我通过重新安装 PHP 解决了这个问题。 (我使用了这个 repo 中的 PHP:ppa:ondrej/php5

以及 HandlerSocket 插入的问题: 1.在循环内创建索引 2.如果通过HandlerSocket进行插入查询最好手动设置id(自增)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-05
    • 2013-05-19
    • 2015-06-04
    • 2016-02-02
    • 2012-09-17
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    相关资源
    最近更新 更多