我需要运行每日PHP脚本,下载数据文件并按顺序执行一堆SQL查询以导入和优化数据。
我在PHP中执行我的一个查询时遇到问题,似乎冻结了我服务器上的mysqld进程。奇怪的是,从Sequel Pro数据库客户端程序(Mac)运行时,运行相同的查询并不会出现类似的问题。
查询在超过一百万行的大型表上运行更新。这是我使用的存储过程:
DELIMITER ;;
CREATE PROCEDURE spSetTripIdInStopTimes()
BEGIN
-- SET META_TRIP_ID IN IMPORT_STOP_TIMES
UPDATE import_stop_times
INNER JOIN ref_trips ON
(
import_stop_times.trip_id = ref_trips.trip_id
AND import_stop_times.meta_agency_id =ref_trips.meta_agency_id
)
SET import_stop_times.meta_trip_id = ref_trips.meta_trip_id;
END;;
DELIMITER ;
使用
调用该过程时CALL spSetTripIdInStopTimes;
在Sequel Pro中,结果是1241483行受影响,所用时间约为90秒。
使用PHP PDO,我使用
运行相同的命令$result = $database->runExecQuery("CALL spSetTripIdInStopTimes");
然而,它在这个查询中停留超过24小时仍然没有完成。当我取消PHP脚本时,我可以看到mysqld进程仍在使用%99.5 CPU。此时,我使用&sudo service mysql restart'重新启动SQL。
我也尝试过使用PHP的mysqli,但这种方法也会发生冻结。
$mysqli->query("CALL spSetTripIdInStopTimes")
是否有人能够解释为什么会发生这种情况或提出另一种方法?
提前谢谢。
注意:我也尝试在PHP上使用较旧的mysql,但我使用的版本(5.5.9-1ubuntu4.14)告诉我该命令已被弃用并停止脚本。
[UPDATE]
我还尝试直接在命令行上运行存储过程:
mysql --user=[username] --password=[password] --execute="call spSetTripIdInStopTimes()" [tablename]
哪个有效。
所以我尝试用PHP exec() function运行相同的命令:
exec("mysql --user=[username] --password=[password] --execute=\"call spSetTripIdInStopTimes()\" [table name]");
不幸的是,它仍然悬而未决。我开始怀疑这是否是由于PHP的限制或开销。
[更新2] 这是我使用的PHP PDO连接选项数组:
array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// Allow file reading, need following settings to import data from txt files
PDO::MYSQL_ATTR_LOCAL_INFILE => true,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::ATTR_EMULATE_PREPARES => true)
[更新3]
我使用自定义数据库对象,因此我将显示$ database-> runExecQuery()的函数以澄清:
function runExecQuery($queryString)
{
$db = $this-> getConnection(); // Connect to database
try{
return array(
"success"=> true,
"data"=>$db->exec($queryString)
);
}
catch (PDOException $ex)
{
return array(
"success"=> false,
"errMessage"=> "ERROR[{$ex->getCode()}]".($this-> Debug ? "{$ex}" : "")
);
}
}
变量$ db是初始化的连接变量,如下所示:
// Create address string
$db_address =
"mysql:host={$settings['db_hostname']};".
"dbname={$settings['db_name']};".
"charset={$settings['db_charset']}";
// Create connection to database
$db = new PDO($db_address, $settings['db_user'], $settings['db_pw'], $options);
其中$ options是[Update 2]中的数组。
[更新4]
Mihai关于改变PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false
的建议有一些有希望的结果,因为查询似乎已经完成。但是,经过更多的测试后,我发现PHP脚本有时会在查询运行时占用50%的时间。即使在SQL表中使用相同的数据集也是如此。