pg_send_query_params返回 TRUE 但失败


pg_send_query_params Returns TRUE But Fails

我有一个PHP脚本,它将一行插入Postgres DB。它在我的测试服务器(Postgres 9.1(上运行良好,但在新的共享主机(Postgres 8.4(上失败。

$query = "INSERT INTO " . $table . " VALUES (DEFAULT, $1, $2, CURRENT_TIMESTAMP::TIMESTAMP(0), $3, $4, ST_Point($4, $3))";
$result = pg_send_query_params($dbconn, $query, array($is_happy, $rate, $lat, $lon));

$result始终为 TRUE,但不插入任何行。

我也试过:

$result = pg_get_result($dbconn);

但经历了同样的行为。

按照下面@CraigRinger的交易建议,我也尝试了这两种方法:

$query = "BEGIN;INSERT INTO " . $table . " VALUES (DEFAULT, $1, $2, CURRENT_TIMESTAMP::TIMESTAMP(0), $3, $4, ST_Point($4, $3));COMMIT;";
$result = pg_send_query_params($dbconn, $query, array($is_happy, $rate, $lat, $lon));

pg_send_query($dbconn, "BEGIN;");
$query = "INSERT INTO " . $table . " VALUES (DEFAULT, $1, $2, CURRENT_TIMESTAMP::TIMESTAMP(0), $3, $4, ST_Point($4, $3));";
$result = pg_send_query_params($dbconn, $query, array($is_happy, $rate, $lat, $lon));
pg_send_query($dbconn, "COMMIT;");

并且仍然有相同的行为。

如果我在phpPgAdmin中运行插入查询,则会插入一行。我还能够在 PHP 脚本中从此查询中获取结果:

"SELECT relid FROM pg_stat_user_tables"

当 INSERT 查询结果为 true 但没有插入任何行时,这意味着什么?可能是什么问题,我该如何解决这个问题?

编辑

我可以使用 phpPgAdmin INSERT行,然后从 PHP 脚本中SELECT这些行。

这是一个失败的完整 PHP 脚本(它被剥夺了我的完整脚本中存在的 POST 收集和验证(。rest.php脚本仅包含连接变量和响应函数。此rest.php脚本适用于我的SELECT脚本:

<?php
require "KLogger.php";
require "rest.php";
ini_set("error_reporting", E_ALL ^ E_NOTICE);
ini_set("display_errors", 0);
ini_set("log_errors", 1);
$log   = KLogger::instance(dirname(__FILE__), KLogger::DEBUG);
$log_id = "AM".time();
$log->logInfo($log_id . " *** " . $_SERVER['REMOTE_ADDR']);
$lat = '51.510199';
$lon = '-0.129654';
$rate = '10';
$is_happy = 't';
$dbconn = pg_connect("host=" . $host . " dbname=" . $db . " user=" . $user . " password=" . $pw);
if(!$dbconn)
{
    $log->logInfo($log_id . " No connection: " . pg_last_error());
    sendResponse(500, "Internal Server Error");
}
else
{
    $query = "INSERT INTO " . $table . " VALUES (DEFAULT, $1, $2, CURRENT_TIMESTAMP::TIMESTAMP(0), $3, $4, ST_Point($4, $3));";
    $result = pg_send_query_params($dbconn, $query, array($is_happy, $rate, $lat, $lon));
    if(!$result)
    {
        $log->logInfo($log_id . " No Result: " . pg_last_error());
        sendResponse(500, "Internal Server Error");
    }
    else
    {
        $log->logInfo($log_id . " sendResponse(200)");
        sendResponse(200, "OK");
    }
}
pg_close($dbconn);
?>

此类问题的最常见原因是未提交的未提交事务。

如果您BEGIN(或通过在数据库驱动程序中关闭自动提交来隐式执行此操作(,则执行一些工作,则只有执行该工作的事务才能看到更改,直到它COMMIT s。

如果是这种情况,那么来自同一脚本中使用相同连接的立即后续查询将看到更改的行,但其他任何内容都不会。

您还可以通过启用以下内容来检查这一点:

log_statement = 'all'
log_line_prefix = 'db=%d pid=%p vtxid=%v txid=%x'

并通过查找具有BEGIN且没有匹配COMMIT的虚拟交易ID(vtxid(来查找不匹配的交易。

如果您因为共享主机而无法修改postgresql.conf,您应该能够ALTER USER myuser SET log_statement = 'all';ALTER DATABASE mydatabase SET log_statement = 'all';。您无法在postgresql.conf外部设置log_line_prefix,但您的主机可能已经具有合理的设置。


另一种可能性(可能由版本差异解释(是,您在事务的后期使用仅在 9.1 中可用的功能触发了错误,并且您没有检测到该错误。前面的INSERT成功,但是当后面的语句失败时,整个事务会回滚。再次检查服务器日志以查看。


另一个常见原因是,您使用脚本连接到的数据库与测试以查看是否已插入的数据库时连接到的数据库不同。插入脚本后,请尝试SELECT您希望已从脚本插入的行。通过您的管理工具(似乎是 phpPgAdmin(创建一个虚拟表,然后测试以查看脚本是否可以看到虚拟表也是值得的。