【发布时间】: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