1

Codeigniter2.0.1とPostgresql8.1を使用しています。私のコードは、try-catchブロック内のトランザクションを使用しています。

単純な挿入で「致命的なエラー」が発生することがあります

致命的なエラー:357行目の<... path ...>/system/database/drivers/postgre/postgre_driver.phpにある非オブジェクトのメンバー関数row()を呼び出す

私のデータベース構成は次のとおりです。

$db['default']['hostname'] = "localhost";
$db['default']['username'] = "***";
$db['default']['password'] = "***";
$db['default']['database'] = "***";

$db['default']['dbdriver'] = 'postgre';
$db['default']['dbprefix'] = '';
$db['default']['pconnect'] = TRUE;
$db['default']['db_debug'] = FALSE;
$db['default']['cache_on'] = FALSE;
$db['default']['cachedir'] = '';
$db['default']['char_set'] = 'utf8';
$db['default']['dbcollat'] = 'utf8_general_ci';

$db['default']['swap_pre'] = '';
$db['default']['autoinit'] = TRUE;
$db['default']['stricton'] = FALSE;

エラーの原因となっているモデルコードのlneは、「$ id = $ this-> db-> insert_id();」です。エラーの原因となる行はinsert_id()メソッド内にあり、モデル内で1回だけ使用されているため、そう言います。モデルのコードスナップショットを以下に示します。

try {

    // CODE TO FILL UP $data ARRAY

    $this->DBquery("BEGIN");
    $this->DBinsert('<TABLE NAME>', $data);
    $id = $this->db->insert_id();

    // SOME MORE CODE
}
catch(Exception $e) {
    $this->DBquery("ROLLBACK");
    //echo $e->getMessage();
    return 0;
}
$this->DBquery("COMMIT");
return $id;

$this->DBqueryと$this->DBinsertは、CI_Modelクラスを拡張する基本モデルクラスで私が作成したカスタムメソッドです。これらのメソッドは完全に機能します。

以下はpostgre_driver.phpのinsert_idメソッドで、357行目は「$ row = $ query-> row();」です。

function insert_id()
{
    $v = $this->_version();
    $v = $v['server'];

    $table  = func_num_args() > 0 ? func_get_arg(0) : NULL;
    $column = func_num_args() > 1 ? func_get_arg(1) : NULL;

    if ($table == NULL && $v >= '8.1')
    {
        $sql='SELECT LASTVAL() as ins_id';
    }
    elseif ($table != NULL && $column != NULL && $v >= '8.0')
    {
        $sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column);
        $query = $this->query($sql);
        $row = $query->row();
        $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row->seq);
    }
    elseif ($table != NULL)
    {
        // seq_name passed in table parameter
        $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table);
    }
    else
    {
        return pg_last_oid($this->result_id);
    }
    $query = $this->query($sql);
    $row = $query->row(); // LINE 357
    return $row->ins_id;
}

問題が常にあるとは限らないので、それはとても混乱します。それは時々起こりますが、仕事を妨げるのに十分な頻度で起こります。このシステムは約8〜10人のユーザーによって使用されているため、同時実行性は問題にならないはずです。また、私はpconnectを使用しており、接続数は無制限です。

4

1 に答える 1

1

これは、insert ステートメントの一部が失敗しているように思えます。このようなトランザクション内でエラーが発生すると、トランザクションが無効になる可能性があります。ログ ファイルを調べると、「現在のトランザクションは中止され、トランザクションが終了するまでコマンドは無視されました」などのエントリが見つかる場合があります。(何が起こっているのかというと、insert_id 関数の $query 変数は有効なクエリ結果値を受け取っていないため、その時点で関数の呼び出しは失敗します)

これを処理する最善の方法は、カスタム DBinsert 関数を変更して、挿入操作の成功または失敗を示す値を返すことです。(内部で実行している挿入コマンドの値を返すことができるはずです)

次に、次のようなことができます。

$insert_ret_val = $this->DBinsert('<TABLE NAME>', $data);
if($insert_ret_val){
    //insert success!
    $id = $this->db->insert_id();
}else{
    //handle failed insert here, rollback, whatever
}
于 2013-02-15T20:59:01.850 に答える