我有一个 PHP 脚本,它生成一个 MySQL 查询,看起来像这样:
INSERT INTO `dailydb`.`probact_actionstaken`(`dispatcher`) VALUES ('kryan');
SET @actionTakenId = LAST_INSERT_ID();
INSERT INTO `dailydb`.`probact_actionstaken_types`(`actionTaken`,`type`)
VALUES
(@actionTakenId, 2);
INSERT INTO `dailydb`.`probact_actionstaken_problems`(`actionTaken`,`problem`)
VALUES
(@actionTakenId, 2);
INSERT INTO `dailydb`.`probact_actionstaken_actions`(`actionTaken`,`action`)
VALUES
(@actionTakenId, 3);
INSERT INTO `dailydb`.`probact_actionstaken_text`(`actionTaken`,`input`,`value`)
VALUES
(@actionTakenId, 3, '7576'),
(@actionTakenId, 4, 'B61'),
(@actionTakenId, 5, '4'),
(@actionTakenId, 6, 'kryan'),
(@actionTakenId, 7, 'test'),
(@actionTakenId, 8, 'testing new debug');
SELECT `index`, `timestamp`
FROM `dailydb`.`probact_actionstaken`
WHERE `index`=@actionTakenId;
(请注意,为了显示此查询,所有值都是手动搜索并替换:someId
为相应值的结果,因为我使用的是准备好的语句)
(还要注意probact_actionstaken
.index
是一个自动递增的主键,并且probact_actionstaken
.timestamp
默认为CURRENT_TIMESTAMP
)
查询的目标是插入大量相关数据(基于 . 的probact_actionstaken
自动值存储index
在)。@actionTakenId
index
timestamp
该查询在大多数情况下都能正确执行:这五个INSERT
语句都在数据库中插入了正确的值。我的问题是最后的SELECT
声明。我尝试使用以下 PHP 代码查看查询结果:
$statement = $dbh->prepare($query);
$statement->execute($params);
$output['results'] = array();
do
{
$output['results'][] = array();
while ( $result = $statement->fetch(PDO::FETCH_ASSOC) )
{
$output['results'][count($output['results'])-1][] = $result;
if ( isset($result['index']) )
{
$output['index'] = intval($result['index']);
}
if ( isset($result['timestamp']) )
{
$output['timestamp'] = $result['timestamp'];
}
}
} while ( $statement->nextRowset() );
echo json_encode($output);
这个想法是使用do...while
块来获取INSERT
语句的结果,然后获取最终SELECT
语句的结果,该结果存储在 my $output
.
在我的本地机器(运行 PHP 5.4.4)上,这非常有效。在具有 PHP 5.3.10 的服务器上,$statement->nextRowset()
每次都返回 false,所以我只得到第一个行集(它是空的,因为它来自INSERT
语句)。请注意,无论如何,实际插入都可以正常工作,并且当我在 phpMyAdmin 的 SQL 功能中运行上述手动填写的查询时,它会返回正确的结果(由插入的索引和时间戳组成的表)。
阅读这些问题,似乎像这样的多个语句是一个坏主意,并且实际上不适用于真正的准备好的语句,而且我仍在使用默认的模拟准备好的语句。所以我可以切换到单独的$dbh->prepare
and调用$statement->execute
,这可以解决我的问题,但我担心竞争条件。服务器使用 Nginx,可能有很多用户同时输入条目。我不想LAST_INSERT_ID()
返回其他用户的条目并将这些字段与错误的操作相关联。
MySQL 或 PHP 中是否有某些原因可以防止出现竞争条件问题?我可以采取一些步骤吗?或者有没有一种安全的方法来使用多个准备好的语句?如果是后者,它是否适用于 PHP 3.5.10?