0

我有一个 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 中运行 INSERT 查询,则会插入一行。我还可以在 PHP 脚本中从此查询中获取结果:

"SELECT relid FROM pg_stat_user_tables"

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

编辑

我可以INSERT使用 phpPgAdmin 行,然后使用SELECTPHP 脚本中的这些行。

这是一个失败的完整 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);
?>
4

1 回答 1

2

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

如果您BEGIN(或通过在数据库驱动程序中关闭自动提交来隐式地这样做)然后做一些工作,只有完成工作的事务才能看到更改,直到它结束COMMIT

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

您还可以通过启用以下方式进行检查:

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

vtxid并通过查找具有 aBEGIN和不匹配的虚拟事务 ID ( ) 来查找不匹配的事务COMMIT

如果您不能修改postgresql.conf,因为它是共享主机,您应该能够ALTER USER myuser SET log_statement = 'all';ALTER DATABASE mydatabase SET log_statement = 'all';. 你不能在log_line_prefix外面设置,postgresql.conf但你的主人可能已经有了合理的设置。


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


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

于 2012-09-04T22:53:48.620 回答