2011-06-23 15 views
2

a flash gameを埋め込んだDrupal 7.2 Webサイトを実行し、プレーヤーの統計情報用のカスタムPHPスクリプトはほとんどありません。 CentOS 5.6/64ビット、PostgreSQL 8.4.8、およびPHP 5.3を使用します。 4GBのRAMを搭載したQuad-Opteronです。トランザクションモードのPHPとpgbouncer:現在のトランザクションは中止されました

ピーク時(オンラインで約500人のプレイヤーがいる場合)、私のWebサイトはあまりにも多くのポストマスタープロセスでダウンしていました。

[databases] 
pref = host=/tmp user=pref password=XXX dbname=pref 

[pgbouncer] 
logfile = /var/log/pgbouncer.log 
pidfile = /var/run/pgbouncer/pgbouncer.pid 
listen_port = 6432 
unix_socket_dir = /tmp 

auth_type = md5 
auth_file = /var/lib/pgsql/data/global/pg_auth 

pool_mode = transaction 
;pool_mode = session 

server_check_delay = 10 

max_client_conn = 200 
default_pool_size = 16 

log_connections = 0 
log_disconnections = 0 
log_pooler_errors = 1 

をとのshared_buffers = 1024メガバイトを増加し、postgresql.conf内= 50をMAX_CONNECTIONSが低下している:pgsql-general mailing listのアドバイスに私は、次の/etc/pgbouncer.iniでpgbouncer 1.3.4をインストールしました。

これは支援してきましたが、私は多くの場合、準備されたPDO文が見つかりませんという問題があります。

おそらく
SQLSTATE[26000]: Invalid sql statement name: 7 ERROR: prepared statement "pdo_stmt_00000016" does not exist 
  • pgbouncerが準備()と(実行との接続を切り替えるために)。

pgbouncerをセッションモードに切り替えることはできません。私のWebサイトはハングします。

PDO :: ATTR_EMULATE_PREPARES => true - 私のウェブサイトもハングします。各周り

私はのbeginTransaction()を追加して(コミットしましたが)(準備)と()の呼び出しを実行する - しかし、私は非常に多くの場合、次のエラーを取得する:

以下
SQLSTATE[25P02]: In failed sql transaction: 7 ERROR: current transaction is aborted, commands ignored until end of transaction block 

は、私のコードの抜粋ですそのエラーで失敗する - それは非常に簡単で、5つのSELECT文を呼び出すだけです:

function fetch_top() { 
     $table  = ''; 
     $top   = ''; 

     try { 
       # throw exception on any errors 
       $options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); 
       $db = new PDO(sprintf('pgsql:host=%s port=%u; dbname=%s', 
         DBHOST, DBPORT, DBNAME), DBUSER, DBPASS, $options); 

       # last week's winner 
       $db->beginTransaction(); 
       $sth = $db->prepare(" 
select u.id, 
     u.first_name, 
     u.avatar, 
     u.female, 
     u.city, 
     m.money, 
     u.login > u.logout as online 
from pref_users u, pref_money m where 
     m.yw=to_char(current_timestamp - interval '1 week', 'IYYY-IW') and 
     u.id=m.id 
order by m.money desc 
limit 1 
"); 
       $sth->execute(); 
       $winner = $sth->fetch(PDO::FETCH_OBJ); 
       $db->commit(); 

       $db->beginTransaction(); 
       $sth = $db->prepare(' 
select count(id) from (
    select id, 
      row_number() over(partition by yw order by money desc) as ranking 
    from pref_money 
) x 
where x.ranking = 1 and id=? 
'); 
       $sth->execute(array($winner->id)); 
       $winner_medals = $sth->fetchColumn(); 
       $db->commit(); 

       # current week leader 
       $db->beginTransaction(); 
       $sth = $db->prepare(" 
select u.id, 
     u.first_name, 
     u.avatar, 
     u.female, 
     u.city, 
     m.money, 
     u.login > u.logout as online 
from pref_users u, pref_money m where 
     m.yw=to_char(current_timestamp, 'IYYY-IW') and 
     u.id=m.id 
order by m.money desc 
limit 1 
"); 
       $sth->execute(); 
       $leader = $sth->fetch(PDO::FETCH_OBJ); 
       $db->commit(); 

       $db->beginTransaction(); 
       $sth = $db->prepare(' 
select count(id) from (
    select id, 
      row_number() over(partition by yw order by money desc) as ranking 
    from pref_money 
) x 
where x.ranking = 1 and id=? 
'); 
       $sth->execute(array($leader->id)); 
       $leader_medals = $sth->fetchColumn(); 
       $db->commit(); 

       # fetch top players 
       $db->beginTransaction(); 
       $sth = $db->prepare(" 
select u.id, 
     u.first_name, 
     u.female, 
     u.city, 
     m.money, 
     u.login > u.logout as online 
from pref_users u, pref_money m where 
     m.yw=to_char(current_timestamp, 'IYYY-IW') and 
     u.id=m.id 
order by m.money desc 
limit 7 
"); 
       $sth->execute(); 
       $i = 0; 
       while ($player = $sth->fetch(PDO::FETCH_OBJ)) { 
         $top .= user_link($player) . ($i++ > 0 ? '' : '&nbsp;&raquo;') . '<br />'; 
       } 
       $db->commit(); 

       # create the HTML table 
       $table = sprintf('.... skipped for brevity ....'); 
     } catch (Exception $e) { 
       exit('Database problem: ' . $e->getMessage()); 
     } 

     return $table; 
} 

助けてください。準備された文は、このモードで動作させるため

をプール アレックス

答えて

0

私はPDOを使用しませんが、セッションモードでpgBouncerを使用して準備済みの文を使用すると、私にとっては効果的です。プリペアドステートメントが正しく動作するように、 "server_reset_query = DISCARD ALL"を設定するだけで済みます。 pool_modeをsessionに設定し、上記の変数も設定できますか?

+0

こんにちは、これはまさに私が昨日やったことです。それはsofar(PDOを使って、beginTransaction/commitなし) –

1

トランザクションは、それがそうしない、内部でそれらを追跡 にPgBouncerが必要になります。 このモードでPgBouncerを使い続けることは準備済みの文 を完全に無効にすることです。

+0

トランザクションプールのドキュメントへのURL:http://pgbouncer.projects.postgresql.org/doc/usage.html#_description @jordaniは絶対に正しいですが、トランザクションプールを使用してください。 – Sean

+0

スクリプトでプリペアドステートメントを無効にする方法はありますか? –

+0

@Sean、申し訳ありませんが、私はあなたのコメントを理解していませんが、 "トランザクションプールを使用"しています。私はすでにそれをやっています。 –

1
  1. あなたPREPARE編文
  2. があなたのPL関数がpg_prepared_statementsシステムビューをチェックし、いずれかが不足している場合は、あなたのプリペアドステートメントのすべてを生成させる作成PL関数を書くtransaction pooling
  3. を使用するように設定pgbouncer
  4. であるためにあなたのSQLコマンドの実行を変更します。
    1. BEGIN
    2. SELECT create_prepared_statements();
    3. /* Do whatever it is that you would normally do */
    4. COMMIT

あなたはまだ-に-BE-これを呼び出す必要があります理由あなたが知らないので、create_prepared_statements() PL関数が書かれていますあなたの接続がディスパッチされているバックエンドか、あなたが話しているバックエンドが新しく生成され、PREPARE ed文がないかどうかを確認します。あなたはPREPAREを使用している方法に応じて

は、彼らが自動的PREPARE「ED文を生成し、キャッシュ以来、SまたはPL機能「VIEWを見て、文を編」は。しかし、PL/pgsql関数をより積極的に使用することをお勧めしますが、これは最も簡単な方法です。

関連する問題