0

Postgres DB に行を挿入する PHP スクリプトがあります。テスト サーバー (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 クエリの結果が true であるのに行が挿入されない場合、これはどういう意味ですか? 何が問題であり、これを解決するにはどうすればよいですか?

編集

INSERTphpPgAdmin を使用して行を作成SELECTし、PHP スクリプトからこれらの行を作成できます。

失敗する完全な 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一致する仮想トランザクション ID ( ) とBEGIN一致しない仮想トランザクション ID () を探して、不一致のトランザクションを見つけCOMMITます。

postgresql.conf共有ホスティングであるため変更できない場合は、ALTER USER myuser SET log_statement = 'all';またはALTER DATABASE mydatabase SET log_statement = 'all';. log_line_prefix外部で設定することはできませんpostgresql.confが、ホストはすでに適切な設定をしている可能性があります。


もう 1 つの可能性 (バージョンの違いによって説明される可能性があります) は、9.1 でのみ使用可能な機能を使用してトランザクションの後半でエラーをトリガーし、そのエラーを検出していないことです。前INSERTのステートメントは成功しますが、後のステートメントが失敗すると、トランザクション全体がロールバックされます。再度、サーバー ログを調べて確認します。


もう 1 つの一般的な原因は、スクリプトが挿入されているかどうかをテストするときに接続したデータベースとは別のデータベースにスクリプトを使用して接続していることです。SELECTスクリプトを挿入した後、スクリプトから挿入されると予想される行を試してみてください。また、管理ツール (あなたの場合は phpPgAdmin のようです) を使用してダミー テーブルを作成し、スクリプトがダミー テーブルを認識できるかどうかをテストすることも価値があります。

于 2012-09-04T22:53:48.620 に答える