PHP + PostgreSQL
■ このスレッドは過去ログ倉庫に格納されています
0001りさあ
NGNG0061名無しさん@お腹いっぱい。
NGNGインタフェースを用意できていないのが問題な気がする。
一度決めたDBを乗り換えようとした場合、ムチャクチャ大変でそ?
この辺、どーにかならんのかね…
0062名無しさん@お腹いっぱい。
NGNGそもそも商用に使っていいんだっけ?
0063名無しさん@お腹いっぱい。
NGNGPHP4 には一応抽象化 DB クラスがあったりしますね。
で、 PHP4 で増えたこのあたりの機能のことを見ようと 「PHP4徹底攻略」を
買ってきたんだけど、 DB 回りのサンプルは PHP3 対応の旧版とほとんど
かわってねーんでやんの。
セッション機能なんかもさらっと触れられてるだけだし。
巻末の役に立たないリファレンスなんかいらないからそのあたり詳しく
書いて欲しかった。
0064電動ナナシ
NGNGあの本はダメだよねえ。というか PHP ユーザー会で Pear に取り組もうと
いう人が広川さん以外にいない時点で、かなり終わっているね。
最近はろくな活動もしていないみたいだし。
いつまでも『PHP + PostgreSQL による高機能 Web の構築』じゃないだろうに。
・どうやったら生産性を高めることができるか
・どうやったら同じコードを何度も書かずにすむか
・どうやったら同じバグに遭遇しないですむか
・どうやったら設計が簡単になるか
・どうやったら設計情報を抜け漏れなく記述できるか
・どうやったら設計情報を共有できるか
・どうやったら実装が簡単になるか
・どうやったらビジネスロジック層と永続化層をきれいに分けることができるか
・どうやったらオブジェクトの永続化が容易になるか
といった課題を解決していかないと、小規模案件の書き捨て用言語以上の存在には
ならないだろうね。で、最初のはクラスを使うことでかなり解決できるし、
二番目のは UML(+ Web 拡張)かな?という気もするし最後のは既存の方法論が
使えるし、十分クリアできるじゃーんとか思うんだけどなぁ・・・。
0065名無しさん@お腹いっぱい。
NGNG言いだしっぺの法則の適用を望みます。
それを本気でやったらPHP界の英雄になれますよ。それだけでは食ってけないでしょうけど (苦笑
0066電動ナナシ
NGNGうひゃあ!うっかり余計なことを言うもんじゃないなあ。
まあ何か出てきたらこの板にて書きますわ。
ちなみに PHP ユーザー会は日本語化についてかなり貢献していることにも
触れておかないと片手落ちだね(もともと日本語化のメンバーが中心だしなあ)。
だからクラスがどうのこうのよりも日本語化にしか関心がないという推測も
できるかもね。
0067名無しさん@お腹いっぱい。
NGNG0068電動ナナシ
NGNG0069電動ナナシ
NGNG>>67
なんのなんの、あれの原型になっていると思われる DBTools.h++ に比べれば
まだまだ素直でしょう。DBTools.h++ に興味があったら
http://www.roguewave.com/support/docs/dbtug/index.cfm
へどうぞ。
冗談はともかく、慣れの問題もあると思うよ。connect->exec->result->close という
手順に慣れていると fetch だのなんだのいったお約束は邪魔に感じるとは思う。
その印象は正しいと思う。
ただ、この手のクラスライブラリは
・どのデータベースにアクセスするにも同一の手順を使える
-> 覚えることは一つでよい
・少なくとも Pear の中のロジックについては信頼して使える。
つまりデバッグすべき範囲を限定できる
という点に大きなメリットがあるから、そのアプリケーションを PostgreSQL
以外の RDBMS に移植するとか、アプリケーションごとに異なる RDBMS を使う
必要があるといった場合にならないとメリットを感じられないかもしれない。
言い換えれば、RDBMS の実装を一つに固定してしまうなら Pear の DB クラスは
それほど威力を持たないということ。自分でアクセスクラスを書いた方が多分
便利だろうね。
0070Error 401
NGNG使い方に誤りがある場合は指摘してください。
・$connectionを公開していないのでpg_set_client_encoding()などを行えない。
・query()もsimpleQuery()もその中でpg_numrows()を実行しているのに、
再度numRows()を実行しなければ行数が分からない。
・Selectする手段がquery(), simpleQuery(), execute()と複数あり、迷ってしますう。
・遅い(単純なページで、ページあたり+20〜+30msかかる)
といったところです。もちろん、extendして自分でクラス定義してしまえばいいんですけど。
0071名無しさん@お腹いっぱい。
NGNGブラックボックスアプリがでかくなるのは当然でそれはシステムで補っていただきませう。
今書いてるモノだと、こいつは絶対エラーにならんから処理省いちゃえ的に
書くこと多いんであとで苦労することが多いんだよね。
classがそれを助けてくれるのなら大歓迎。
次のシステムで実験させて貰います。
0072電動ナナシ
NGNG> ・$connectionを公開していないのでpg_set_client_encoding()などを行えない。
simpleQuery とかで simpleQuery("SET clientencoding TO 'EUC_JP'"); とか
して対処できない?
simpleQuery は単純に pg_execute(${simpleQuery の引数}) しているだけ
だからこれで動くと思うんだけど。
> ・query()もsimpleQuery()もその中でpg_numrows()を実行しているのに、
> 再度numRows()を実行しなければ行数が分からない。
ソース見てちょっとびっくり。この辺の扱いって実装ごとに異なっているんだ。
ううむ・・・。
PostgreSQL 前提だと、Qeury のたびに DB_pgsql のインスタンス(仮に $pgsql と
するよ)の $numrows に行数が格納される。で、$pgsql->numrows[$result] で
アクセスできる。
肝心の $result だけど、simpleQuery の場合は単純にその戻り値を使えばいいし、
query() の場合には戻ってきた DB_result 型のオブジェクトの $result に
アクセスすればいい。例えば $resultObj->result とか。
0073電動ナナシ
NGNGsimpleQuery と query はともに直ちに実行可能な SQL 文を渡して処理するメソッド。
ただ、前者の場合には戻り値が pg_result で利用可能な結果識別子なのに対して、
後者は DB_result 型のオブジェクトが返るところが違うようだね。
execute() は prepare() とセットで実行されることが前提。で、prepare() に渡す
SQL 文には、? と & という特別なバインド変数を定義できて、前者の場合には
第二引数で渡された値(配列中の値)が、後者の場合には渡された値と同じ名前を
もつファイルの中身を SQL 文の中に結合することができるみたい。
> ・遅い(単純なページで、ページあたり+20〜+30msかかる)
>>71 さんのおっしゃる通りだと思う。
あとは Zend Cache 使うとか・・・。
0074Error 401
NGNGインスタンス変数って、プライベートだと思っていたら、パブリック
だったんですね。
道理で、アクセッサメソッドが無いわけだ。
それから、各メソッドの説明どうもです > 電動ナナシさん
prepare() & execute()の機能には、ビックリです。
>prepare():
>Prepares a query for multiple execution with execute(). With
>PostgreSQL, this is emulated.
じゃ分からんぞ(w
0075Error 401
NGNG>simpleQuery とかで simpleQuery("SET clientencoding TO 'EUC_JP'"); とか
>して対処できない?
simpleQuery("SET client_encoding TO 'EUC_JP'")
でOKでした。
0076Error 401
NGNG$ret = $db->simpleQuery("set client_encoding to 'EUC_JP'");
if ($ret != DB_OK) {
  exit;
}
とやったところ、エラーが発生してもexitしない。
これは、エラーが発生したときに、$retに文字列が入っていて、
比較するときに文字列->数値という変換がなされ、
if (0 != 0)
という比較になるので、このifブロックには絶対に入らない。
正しくは、
if ($ret !== DB_OK)
とする必要がある。
・・・という解釈は正しいですか?
0077Error 401
NGNG(1)のエラー判定は、こうするしかないのでしょうか?
ほかに判断の方法はありますか?
require("DB.php");
$db = DB::connect("pgsql://localhost/testdb");
if (DB::isError($db)) {
  exit;
}
$sql = "select emp_code, emp_name from emp";
$res = $db->query($sql);
if (get_class($res) != "db_result") {    // (1)
  exit;
}
//echo $db->numrows[$res->result] . "<br>\n";
echo "<table>\n";
while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
&nbsp;&nbsp;echo "<tr><td>$row[role_name]</td><td>$row[emp_name]</td></tr>\n";
}
echo "</table>\n";
0078電動ナナシ
NGNGちょっと今余裕がないので、1点だけ。
simpleQuery() は Protected な Method なんだと思う。
何でかというと、simpleQuery() の戻り値は実装依存になって、実装の詳細を
隠蔽しようという DB クラスの意図に反するから。
じゃあなんで simpleQuery() なんてあるのかというと、クラスを拡張するときに
実装を意識しないといけないときのためにあるんだと思う。言い換えれば、
extend したクラスからのみこのメソッドは用いられるということ。
だから DB クラスを普通のアプリケーションから使うときには query() を使って
DB_result 型の結果を取得し、fetchRow() するのが正しい使い方になるんだと思う。
ここのサンプルコードも見てみて。query() 使っているよ。
"Best Practices: Database Abstraction"
http://www.phpbuilder.com/columns/allan20010115.php3
エラー判定については後でね。
0079Error 401
NGNG電動ナナシさん、毎度どうもです。
PHPBuilderの記事をざっと読みました。
# ここ、良い記事がたくさんありそうですね。
そして、わかった&考えたこと。
・ DB.phpの思想は、DB::isError($obj)でエラー判定をする。
・ そして、DB::errorMessage($obj)でエラーメッセージを獲得する。
・ mysql.phpは確かに、query()が失敗すると、raiseError()している。
・ ところが、なぜだかpgsql.phpでは、query()が失敗すると、直接エラー
メッセージを返している。
・ なので、DB::isError(query())というお決まりパターンが使えない。
他のDBのライブラリを全部見たわけではありませんが、DB.phpの
isError()の実装を見る限り、pgsql.phpの実装に一貫性が欠けている
気がします。
0080Error 401
NGNGのしくみがきちんと機能するのは、MySQLだけみたいな気が。
>>79は間違っているのかなぁ?
0081Error 401
NGNGPEARの目標だと思うのだけれど・・・。
0082電動ナナシ
NGNGそうなんだよね。まだまだ発展途上。ドキュメントもないし。
そのうちクラス図を作って公開する予定。
>>80
>>79 は合ってる。それで正解。というか DB に限らず PEAR 共通の例外機構のような
ものを作りたいみたいなんだよね。で、
・メソッド実行して、成功なら普通のオブジェクトを、失敗なら PEAR_error 型の
オブジェクトを返す
・オブジェクトについて isError($returnedObject) で成功・失敗を判定
という風にしたいような感じなんだなあ。
MySQL と OCI8 は確かにエラーが起きると raiseError() して DB_error 型
(こいつは PEAR_error を継承している)を生成して返すようになっているけど、
DB_pgsql.php はそうなっていないという点が問題みたい。
広川さん(DB_pgsql の開発者)に連絡するか、自分でパッチ送って submit すると
喜ばれるんじゃない?自分も暇が出来たらやってみよう。
0083電動ナナシ
NGNGしかない)んだよね。それで実装されてないって可能性が大きいかも。
DB_pgsql.php の errorNative() のコメントを見てそう思った。
0084Error 401
NGNGhttp://lxr.php.net/source/php4/pear/DB/pgsql.php
を発見しました。
・・・ォィォィ、おもいっきり、実装かわっとるやん。
とりあえず、simpleQuery()でエラーが発生した場合、raiseError()
しているのを確認しました。
# pgsql.phpには、query()が無くなってます。
PHPもPostgreSQLも最近始めたばかりで、php-mlの近藤氏が
どのような人かは知りませんが(でも、発言力ありそうな雰囲気)、
> ソースコードをみて、バリバリ自社で保守するだけの
> 技術力と体力のあるとこは別だけど、私なんか、とて
> も使う気になれません。テストも終ってないコードを
> 使う位なら、レベルは低くても責任もってユーザー
> サポートできる自前のツールの方がいいです。
というのは悲しいね。
DBの抽象化ライブラリとして現在も標準添付されているし、
おそらく将来もそうであろう「PEAR」なんだから、
どんどん使って、ノウハウを溜め込み、その思想を学ぶ
べきなんじゃないかなぁ、なーんて、思いますけど。
sourceforge.netを見ても、PHPのDB abstract libraryは
両手でも足りないくらい(ウソかも)あり、とても全てを
評価するなんて出来ません。
みんながそれぞれ、ちょっとづつ違うDBライブラリを作るなんて、
それこそ非生産的です。
# ところで、PEARのアノニマスCVSリポジトリってあるんでしょうか?
0085Error 401
NGNG検索したら、ありました。(先に検索しろ>自分)
cvsweb:
http://cvs.php.net/viewcvs.cgi/php4/pear/
pserverもありました。
0086電動ナナシ
NGNGあなた、すごいね。:-)
近藤さんの言いたいことも分かるけど、
> みんながそれぞれ、ちょっとづつ違うDBライブラリを作るなんて、
> それこそ非生産的です。
これに大いに賛成。
ただ近藤さんが一番心配しているのは SQL (DDL/DML) の互換性の問題だと思う。
サブセレクト(副問い合わせ)の対応の有無とか、トランザクションの
構文とか、ロックの構文とか実装によって全然違うからね。
# 先の PG_CLIENT_ENCODING もその問題の一つ。
だからデータ操作まで完全に抽象化するのに Pear じゃダメというのはある程度
理解できる。
ただ、アクセス方法やエラーハンドリングを標準化する意義は十分あると
思うなあ。JDBC に批判的なように、近藤さんはこの手の抽象化ライブラリ
全般に不信感があるのかもしれない。
# ODBC では確かにひどい目にあったな。
コードの信頼性は、チャレンジャー(人柱)の犠牲によって獲得していく
しかないだろうね。すると人柱が一番多いのはどれだ?という話になると
思う。今のところ PHPLib > Pear >> その他 という感じかなあ。
0087Error 401
NGNGAbstract DB Libraryの目的(ターゲット)としては、例えば
SQL92 Entry Levelとかを想定して、実装していけばいいん
じゃないかなー、なんて思います。
ここ数年Oracleをやってきたんですが、最近PostgreSQLを始めて、
特にそう思います。
PEARのDBライブラリは、OracleのBC4Jなどと違って(BC4Jの
場合、DMLを一切使わずにプログラミングします。もちろん、
使おうと思えば使えます)、DMLは自分で書く、というスタンス
なので、DBの違いによるSQLの違いはライブラリ側で吸収する
必要が無いのです。
DBライブラリは、SQLをDBに送って、結果のレコードセットなり、
完了値を戻せばよいのです。
PHP-jpを見てて思うのは、クライアントアプリケーションの機能を
実現するためのコードと、ライブラリのコードをごっちゃに論じて
いる気がします。
現時点で言えば、例えばOracleとPostgreSQLを同じDBライブラリを
使って同じコードで、どちらのDBでも動くようにしようと思うのなら、
ViewやストアードサブプログラムやトリガーなどのDBエンジン内の
仕組みを駆使するしかありません。もちろん、それらのDBエンジン
側のプログラムやDDLのコードは、各DBで違うのですけど。
PEAR(というか、抽象化DBライブラリ)を使えば、クライアント
アプリケーションのコードは同一で、複数DB対応は可能だと思います。
もちろん、DB管理ツールなどは、同一のコードなどは望むべくも無く、
ゴリゴリにターゲットDBに依存しまくったものじゃないと使い物に
ならないんじゃないかなー。
なんか、とりとめが無くなってきたのでこのへんで。
0088Error 401
NGNG>ただ、アクセス方法やエラーハンドリングを標準化する意義は十分あると
>思うなあ。JDBC に批判的なように、近藤さんはこの手の抽象化ライブラリ
>全般に不信感があるのかもしれない。
それは、よーくわかります。
>コードの信頼性は、チャレンジャー(人柱)の犠牲によって獲得していく
>しかないだろうね。すると人柱が一番多いのはどれだ?という話になると
>思う。今のところ PHPLib > Pear >> その他 という感じかなあ。
私はPHP4.0.4から入ったので、PHPLibは使ったことないのですが、
それに慣れて、しかも発言力ある人たちが、「Pearは不安定だ、
未完成だ、使えないぞー」と声高に(というのは私が受け取った
印象ですが)言うのは、やめて欲しいなー、という感じですね。
0089Error 401
NGNGなにしろ、時間が無い・・・。来週末までに、今作っているシステムを
完成しないといけないんです(グチ)。
誰か最新版を追っかけて、評価する人いないかなー。
# 結局、他人を頼るのかいっ! (w
0090Error 401
NGNG忙しい人の為に、目次を引用。
V PEAR: the PHP Extension and Application Repository
23 章 PEARについて
- PEARとは?
24 章 PEAR コーディング標準
- インデント
- 制御構造
- 関数のコール
- 関数の定義
- コメント
- コードの読み込み
- PHPコードのタグ
- ヘッダのコメント部
- CVS タグ
- URLの例
- 定数の名前
LXXXIII PEAR リファレンスマニュアル
- PEAR PEAR基底クラス
- PEAR_Error PEARエラー処理機能の基底クラス
やはり、PEARのエラーハンドリングの思想は、エラーオブジェクトを
返す、というので正解でした。
0091電動ナナシ
NGNGquery() は DB_common.php に移動したみたいだね。で、query() では simpleQuery() を
中で呼び出して使っている。こっちの方がエレガントでいいよなあ。
# Refactoring だね。:-)
>>87
思いっきり同意。
「何をクラスライブラリで共通化するか」という議論が抜け落ちている感じがするね。
009247
NGNG>>48と>>50で教えていただきました方法を試してみました。
GRANT SELECT ON (VIEWのテーブル名) TO PUBLIC;
ですが、この場合PUBLICとは誰にでも許可するというような意
味合いと解釈したのですが、実際にはまだエラーが続いてしまい
ます。
nobodyは上記publicとは全く別者なのでしょうか?
GRANT SELECT ON (VIEWのテーブル名) TO nobody;
とする必要があるのでしょうか?(実際試してみればいいとは思
うのですが、何か解説等があれば教えていただきたく思いました。)
0093ゾリ大佐
NGNGpostgresアカウントでcreateuser nobodyしてみました?
009447
NGNGおっしゃる通り、nobody自体のアカウントが作成してありませんでした。
目標とする結果はブラウザ上に現れませんでしたが、今回は間違いなくDB
への接続は出来ているようです。
私のスクリプトが間違っていると思われ、ブラウザ上には何もエラーメッセ
ージは出ませんが、画面は真っ白でした。
今度こそ、ゆっくりスクリプトの方に挑戦してみます。
また判らないことありましたらお伺いさせていただきます。
009547
NGNGまだ勉強を始めたばかりのため、複雑なSQL文やPHPのスクリプトは書けませんが、
取り敢えずブラウザ上にデータが表示されたことには感動しました。
0096名無しさん@お腹いっぱい。
NGNG例)1000 → 1,000 のように。
お願いします。
0098名無しさん@お腹いっぱい。
NGNG金額の表示OKでした。
どうもありがとうございました。
0099Error 401
NGNGhttp://www.zend.com/codex.php?CID=10
英語では、「抽象化DBクラス」を「Database Abstraction Class」って
言うみたいですね。
0100Error 401
NGNGnews.php.net
PEARもあるよ。
おまけ:CVS currentなPEARのサンプルです。
require("DB.php");
$db = DB::connect("pgsql://localhost/fdkwf");
if (DB::isError($db)) {
&nbsp;&nbsp;exit;
}
// echo $db->toString() . "<br>\n";
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$sql = "select emp_code, emp_name from emp";
if (DB::isError($res = $db->query($sql))) {
&nbsp;&nbsp;echo DB::errorMessage($res);
&nbsp;&nbsp;exit;
}
echo "<table>\n";
while ($row = $res->fetchRow()) {
&nbsp;&nbsp;echo "<tr><td>$row[emp_code]</td><td>$row[emp_name]</td></tr>\n";
}
echo "</table>\n";
$db->disconnect();
0101Error 401
NGNGPostgreSQL 7.1beta6が出てたのでインストールしました。
やっとDEBUGメッセージがpsqlにも出るようになった。
これが無いと、デバッグきついからね。
beta5でバグってた、serial型も修正されてた。
マニュアルに、『Porting from Oracle PL/SQL』が追加されてた。
テキスト換算で500行くらいのドキュメント。
マニュアルは、beta5から、かなり増えてる。
0102Error 401
NGNGChangeLog:
> 2001-03-16 08:03 inoue
>
> * src/interfaces/odbc/: multibyte.c, multibyte.h: Oops I forgot to
> add new files for multibyte support. Sorry Eiji.
だったらしい。
0103Error 401
NGNGウソ書いてる可能性大。
0104名無しさん@お腹いっぱい。
NGNGtelnet www.hoge.com 5432
ってやってなんかコマンドを打ってみたいのですけど
なにうてばいいのでしょう?何打っても
EInvalid packet lengthConnection closed by foreign host.
とでてしまうのです。やさしいお兄さんおしえてください。
0105電動ナナシ
NGNG普通に psql の感覚でコマンド打ってもダメだよ。
http://www.postgresql.org/docs/programmer/protocol.htm
0107名無しさん@お腹いっぱい。
NGNGGET,Hidden以外でできるのでしょうか?
Hiddenを使用しないページは、ユニークなIDが
渡っているような気もしますが・・。
他にデータを格納して、次のページでそのIDを参照し
データを取得してるとか・・。
どうされてるんでしょうか?
0108名無しさん@お腹いっぱい。
NGNGPHP4なら、sessionを使えばできる。マニュアルの
LXVIIIセッション処理関数
を参照。
0109名無しさん@お腹いっぱい。
NGNG判らず困っております。
フォーム(test1.php3)からデータを受取り、それをデータベース(Postgre SQL)
へ登録する際、それを処理するページがtest2.php3とお考え下さい。
登録用フォームにはtext形式でname="cr"という項目にデータを入力
してもらいます。
因みにPostgre SQL側ですが、crにはNull不可としてあります。
ここでデータ登録は問題なく処理が出来ました。
しかし、もしデータが何も入っていない時と、test1.php3をブック
マークとかに登録されていた場合には、直接このページへ入って来
た時にエラー表示を出したいと思いました。
そこでただinsert処理をしていたスクリプトにエラー処理用のスクリ
プトを追加してみたいと思ったのですが、どうにも上手に処理出来ま
せん。
この場合、以下のスクリプトで解決する方法はどうすればいいでしょ
うか?
// ここにfunctionを設定?
if(ここに何をいれるのか?)
{
print('エラーです'\n);
}
ellse
{
現在使用しているinsert処理用のスクリプト
}
宜しくお願いいたします。
0110109
NGNG自分で解決出来たと思われます。
ついWindowsの癖で、フォームで使用するタグにvalue="$cr"を入れておらず、
それが問題だったような気がします。
if($cr == "")
{
print("エラーです\n");
}
else
{
insertの処理
}
で問題なさそうな気がします。(現在テストした結果ですが)
何か問題があるような場合、ご指摘いただけましたら幸いです。
0111名無しさん@お腹いっぱい。
NGNG電動ナナシさんありがとうございました。
ちょっとむずかしくて解りませんでしたけど。
もしよかったらなんかサンプルコードありませんか?
例えばpg_userにアクセスするような。
HTTPがわかりやすすぎるのでしょうか?はぁ。
0112Error 401
NGNG$ cvs update
P common.php
P mysql.php
P odbc.php
P oci.php
common.php以外は、PostgreSQLには関係無いけど :-P
ちなみに私はPEARに全面移行しました。
0113Error 401
NGNG持続的接続を使ってる人います?
なんか、動きがおかしいんです。
1. php.ini : pgsql.max_persistentの値より、プロセスが増える。
2. 'now'::timestampの値がおかしい。
1.は、テストとして10を設定してるんですが、プロセスが10を超えてしまいます。
どこまで増えるかは不明。
2.は、ストアードファンクションの中で、
insert into tbl(col) values('now'::timestamp)
とやると、過去のtimestampが記録されることがあります。
ひょっとすると、過去に立ち上がったプロセスに接続されると、
この現象が起きるのかもしれませんが、良くわかりません。
・・・というわけで、現在は持続的接続は使っていません。
でも持続的接続にすると、ページあたり、-30ms位になるんだけどなぁ。
0114名無しさん@お腹いっぱい。
NGNG持続的接続はhttpdのpidごとに張るんですよね。
だからプロセスが変わるってのは変なのではないでしょうか?
ストアドだから張ったときのnow読んでいるって言う可能性は
ないのでしょうか?
この板にがんばって発言してみようと思ってるんですけど
ほんとど素人であーぱーナこといってすいません。
0115電動ナナシ
NGNGソース見たけどよくわからんなあ。
チェックは働いているみたいなんだけど。
全プロセスで pConnect() してるの?
どこかで Close() したりしてない?
daemontools 使って PgSQL 側の接続状況調べて、同時に何コネクション
張りにきているか調べてみたら?
http://tanaka-www.cs.titech.ac.jp/~euske/doc/daemontools.html
0116Error 401
NGNGうーん、昨日から持続的接続のテストを始めて、
今日になって、'now'::timestampに昨日の日付のものが
登録されるようになったんです。
サーバは、昨日から立ち上げっぱなし、
クライントは、今日立ち上げたもの
です。
持続的接続は、クライアントがいなくなった場合、そのプロセス
は残っていて、接続要求があったときに、空いてるプロセス
があれば、そこにつなげる、というふうに思ってたんですが、
間違いでしょうか?
0118Error 401
NGNGdaemontoolsは、ちょっとスケジュールが厳しいので、
インストールして、調査、っていうのは厳しいなぁ。
来週火曜日までに、ひととおり作り上げ、来月稼動なので。
来週火曜日で承認されたら、また調査してみます。
0119電動ナナシ
NGNGいいよね。で、close() すると持続的接続でも接続解除されるというのも
いいよね。
で、持続的接続の場合には次のようになる。
例えば pgsql.max_persistent = 2 とするよ。
最初に pConnect() するよね。
・PHP の持続的接続数 = 1
次に pConnect() するよね。
・PHP の持続的接続数 = 2
次に pConnect() すると失敗
・持続的接続数 > max_persistent が成立
でも、次の場合はうまくいく。
最初に pConnect() する。
・PHP の持続的接続数 = 1
次に pConnect() する。
・PHP の持続的接続数 = 2
どれかがいったん close()
・PHP の持続的接続数 = 1
次に pConnect() する。
・PHP の持続的接続数 = 2
こんな感じになると思う。間違っていたらスマン。
0120電動ナナシ
NGNGpConnect 関数は、過去の接続を覚えていて
・以前接続したのと同じコネクションがあれば、それを再利用
・そうでなければ接続
を行う。
で、「以前と同じ接続」かどうかは
"pgsql_HOSTNAME_PORT_OPTIONS_TTY_DBNAME"
という文字列で判断される。つまりホスト名、ポート番号、接続オプション、
端末名、データベース名の組み合わせがいっしょなら同じ接続、
そうでなければ別の接続になる。
pgsql.max_persistent は上記組み合わせの個数を制限するもの。
仮に Apache のプロセス数が 100 あっても、同じホストの同じ DB に接続
するなら、コネクションは一つしか張られないから max_persistent の
制限にはひっかからない。
あるコネクションへのアクセスが許可される Apache のプロセス数ではないよ。
0121電動ナナシ
NGNG・セッション確立のコストが大きい(メモリと CPU に負荷を与える)
・WWW の場合、リクエスト単位で接続するとセッション確立・破棄が
頻繁に行われることになり、さらに負荷がかかる
から。
で、複数リクエストを一つのデータベースセッションで処理することで
この問題を解決しようということで、持続的接続というアイデアが
生まれたんだよね。確かもともとはミドルウェア(トランザクション
モニタの Connection Pooling 機能)だと思った。
0122Error 401
NGNG> いいよね。で、close() すると持続的接続でも接続解除されるというのも
> いいよね。
ん、勘違いしてました。
close()で接続解除されるのは、あくまでも「仮想接続(勝手に名前
付けました)」で、httpd <-> postgresの接続は残るものだと思って
ました。じゃないと、postgresのプロセスが死なないことに説明
がつきません。
そもそも、close()しても、このpostgresのプロセスが残る、という
のが、何かおかしいのでしょうか?
# OracleのBC4Jにおけるコネクションぷーリングの考え方とは
# かなり違うなぁ。
※仮想接続とは、ブラウザ <-> httpdのHTTPセッションを越えた、
複数HTTPセッションにまたがる、仮想的なDBコネクションを
指しています。
> "pgsql_HOSTNAME_PORT_OPTIONS_TTY_DBNAME"
> という文字列で判断される。つまりホスト名、ポート番号、接続オプション、
> 端末名、データベース名の組み合わせがいっしょなら同じ接続、
> そうでなければ別の接続になる。
うーむ、テストは同じクライアントから、同じデータベースへの
接続を、同じユーザ名、パスワードで繰り返すものだったから、
やっぱりPostgresのプロセスが増殖していくのは納得いきません。
# PostgreSQL 7.1RC1出てますね。
0123電動ナナシ
NGNGPostgres が残るってのは不思議だなあ。勘違いしてるかもしれないので、
ちょっと調べてみる(ちゃんと確認しているわけじゃなかったので)。
PostgreSQL と Apache/PHP は同じサーバーで動いているの?
lsof 入れてみて、どの Postgres プロセスが誰とお話しているか調べて
みたらどうだろ?
0124Error 401
NGNG電動ナナシさん、いつもどうもです。
なんか、お手間を取らせてしまってすみません。
今、とんでもなくテンパッテるので、私の方の再試は水曜日以降に
なります。
0125名無しさん@お腹いっぱい。
NGNG> 2.は、ストアードファンクションの中で、
> insert into tbl(col) values('now'::timestamp)
> とやると、過去のtimestampが記録されることがあります。
これは、'now'::text にしなくちゃ、って話じゃなかったらスマソ
0126Error 401
NGNG.> これは、'now'::text にしなくちゃ、って話じゃなかったらスマソ
むむ。
test=# select 'now'::text;
とやると、
?column?
----------
now
(1 row)
となるのですが・・・。
# PostgreSQL 7.1beta6です。
# 運用開始までに、7.1出るのだろうか・・・。
0127名無しさん@お腹いっぱい。
NGNGいや、そうじゃなくて、トリガーとかで 'now'::timestamp って
するとトリガー生成時点の 'now' になっちまうんで、'now'::text
にしとくって話。
0128Error 401
NGNGあっ。理解できました。
で、いろいろ調べたんですが、
CURRENT_TIMESTAMP -- SQL92準拠
now() -- PostgreSQL固有?
'now'
のどれでも、現在時刻を返してくれます。
> いや、そうじゃなくて、トリガーとかで 'now'::timestamp って
> するとトリガー生成時点の 'now' になっちまうんで、'now'::text
> にしとくって話。
そういえば、この話どこかで見覚えがあるんですが、
マニュアルに載ってるのですか?
マニュアルは、ローカルでNamazu化してるんですけど、
検索できませんでした。
0130Error 401
NGNG[環境]
PHP 4.0.4pl1 (pearはCVS currentのもの)
PostgreSQL 7.1RC1
使ったソースは以下。
-- test.php ---------
<?php
&nbsp;&nbsp;require("DB.php");
&nbsp;&nbsp;$db = DB::connect("pgsql://localhost/test", true);
&nbsp;&nbsp;if (DB::isError($db)) {
&nbsp;&nbsp;&nbsp;&nbsp;echo "Connect failed.";
&nbsp;&nbsp;&nbsp;&nbsp;exit;
&nbsp;&nbsp;}
&nbsp;&nbsp;echo "Connect success.";
&nbsp;&nbsp;$db->disconnect();
?>
----------------------
PostgreSQLは、
pg_ctl start -o -i
で起動。
-- php.ini -------------------
pgsql.allow_persistent = On ; allow or prevent persistent link
pgsql.max_persistent = 10 ; maximum number of persistent links. -1 means no limit
pgsql.max_links = -1 ; maximum number of links (persistent+
-------------------------------
続く。
0131Error 401
NGNG→postgresのプロセスは残ったまま
・そのまま何回かリロードしてみる。
→postgresのプロセスは残ったまま。ただしプロセス数は増えない。
・時間を置いてリロードしてみる。
→規則性はわからないが、あるタイミングでプロセスは増えていく。
・どこまで増えるかはわかりません。
ps -ef | grep postgresの結果
postgres&nbsp;19528&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;0&nbsp;09:27&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00:00:00&nbsp;./postmaster&nbsp;-D&nbsp;/usr/local/pgsql
postgres&nbsp;23715&nbsp;19528&nbsp;&nbsp;0&nbsp;10:02&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00:00:00&nbsp;postgres:&nbsp;nobody&nbsp;test&nbsp;127.0.0.1
postgres&nbsp;23723&nbsp;19528&nbsp;&nbsp;0&nbsp;10:04&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00:00:00&nbsp;postgres:&nbsp;nobody&nbsp;test&nbsp;127.0.0.1
postgres&nbsp;23813&nbsp;19528&nbsp;&nbsp;0&nbsp;10:12&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00:00:00&nbsp;postgres:&nbsp;nobody&nbsp;test&nbsp;127.0.0.1
postgres&nbsp;24841&nbsp;19528&nbsp;&nbsp;0&nbsp;10:26&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00:00:00&nbsp;postgres:&nbsp;nobody&nbsp;test&nbsp;127.0.0.1
続く。
0132Error 401
NGNGとりあえずオプション無しの結果。
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;3,65&nbsp;&nbsp;1651925&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;817675&nbsp;/home2/local/pgsql7.1RC1/bin/postgres
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;&nbsp;492888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;180226&nbsp;/lib/ld-2.1.3.so
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;&nbsp;&nbsp;79474&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;180244&nbsp;/lib/libcrypt-2.1.3.so
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;&nbsp;197984&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;180288&nbsp;/lib/libresolv-2.1.3.so
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;&nbsp;523855&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;180236&nbsp;/lib/libnsl-2.1.3.so
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;&nbsp;&nbsp;72276&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;180272&nbsp;/lib/libdl-2.1.3.so
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;&nbsp;545453&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;180228&nbsp;/lib/libm-2.1.3.so
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;&nbsp;174341&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;639164&nbsp;/usr/lib/libreadline.so.4.0
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;&nbsp;&nbsp;14837&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;180309&nbsp;/lib/libtermcap.so.2.0.8
postmaste&nbsp;24841&nbsp;postgres&nbsp;&nbsp;mem&nbsp;&nbsp;&nbsp;&nbsp;REG&nbsp;&nbsp;&nbsp;&nbsp;3,7&nbsp;&nbsp;5309068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;180230&nbsp;/lib/libc-2.1.3.so
[考察]
うーん、全く進歩なし(^^;
0133Error 401
NGNGさっきのプロセスが残っている状態で見てみると、
Active Persistent Links 0
Active Links 0
disconnect()なしでスクリプトを実行すると、
Active Persistent Links 1
Active Links 1
その状態で、disconnect()すると、
Active Persistent Links 0
Active Links 0
プロセスは1個増えました。
ちなみに、これらのプロセスは24時間たっても消えません。
Apacheを止めると消えます。
[考察]
PHPの持続的接続のリンク数の管理はうまくいっているみたい。
プロセスの生成・消滅条件は、いまだわからず。
0134Error 401
NGNG報告しておきます。
結局、現状理解の糸口さえ見つからない状態なので、
持続的接続を使うのは、とりあえず止めます。
PHP4.0.5 + PostgreSQL7.1がそろったあたりで、再チャレンジします。
0135Error 401
NGNG仕事の合間に、いろいろとWebを検索してみたら、
「postgresプロセスが死ぬのは、対応するapacheプロセスが
死んだとき」
という情報にあたりました。
どっかの英語のBBSです。
今使っているサーバは、apacheを起動すると、apacheのプロセスが
10個立ち上がります。
で、これに空きがある場合は、HTTPリクエストをこれらのプロセスが
処理します。HTTPセッションが終了しても、これらのプロセスは
残ったままです。
持続的接続で立ち上がったpostgresプロセスは、これらのプロセス
との間に、DBセッションを確立します。
だから、close()しても、postgresプロセスは残ったままなんです。
・・・という線で自分を説得。多分正解。
0136電動ナナシ
NGNGソースちょっと追ったけど、connect() の場合と pconnect() の場合とで
ほとんど同じ処理をしているんだよね。単にリンク数のカウンタ処理部分が
違うくらいで。
connect() だと postgres は死んでくれるの?
謎だあ。もうちょっと追ってみよう。
# 暇ができたらだけど・・・。
0137Error 401
NGNG>connect() だと postgres は死んでくれるの?
はい、死んでくれます。
>謎だあ。もうちょっと追ってみよう。
念の為書いときます。
configure optionの --enable-sigchildが、Oracleの持続的
接続を使う場合には必要という情報を見つけ、
リコンパイルしてみたんですが、これは関係ありませんでした。
オプション無しの場合と全く同じ挙動でした。
0138電動ナナシ
NGNGなんとなく原因がわかった雰囲気。
ひょっとして PostgreSQL だけでなく、あらゆる持続的接続の Close が
きちんとされてないという予測を立てたんだけど、追試できる人っている?
0139名無しさん@お腹いっぱい。
NGNGclose で close されたら、pconnect の意味なし
0140電動ナナシ
NGNG馬鹿さらしてしまった。鬱だし脳。
0141名無しさん@お腹いっぱい。
NGNGバックエンドをpreforkさせるための便宜的手法。
fastcgi みたいなものと言った方がわかりやすい?
0142Error 401
NGNGしかし、話題になりませんね・・・。
0143電動ナナシ
NGNGPostgreSQL の場合、ホビーよりビジネスでの利用が多いから、
安定性が確認されていないベータ版には興味がないのかもしれないね。
そういえば PHP-jp に pConnect() 時の Backend の数を質問していた人が
いたけど、回答がなかったね。
あと一応確認。そんなことも知らんのかって言われそうだけど・・・。
Module 版の PHP の場合、Apache で fork() された分だけプロセスが
あると思っていいんだよね?。例えば Process ID が 1000 な httpd と
1001 な httpd がある場合、httpd に組み込まれた PHP はそれぞれ
別々のプロセスとして動作するんだよね。
そうだとすると persistent_links や max_links は httpd プロセス
ごとに効くことになるから、Process 数 x {persistent|max} links に
なるのは当然ということか。
# これらの数字は PHP/Zend Process ごとに保有されるみたい。
0144名無しさん@お腹いっぱい。
NGNG>PostgreSQL の場合、ホビーよりビジネスでの利用が多いから、
>安定性が確認されていないベータ版には興味がないのかもしれないね。
7.1前提でシステムを作っている私って・・・
# 4/23リリース予定。それまでにRelease版出るかなー?
>そういえば PHP-jp に pConnect() 時の Backend の数を質問していた人が
>いたけど、回答がなかったね。
すぐに自己フォローしてたから・・・。
ちなみに、あれは私じゃありません。
>Module 版の PHP の場合、Apache で fork() された分だけプロセスが
>あると思っていいんだよね?。例えば Process ID が 1000 な httpd と
fork()って、PHPのプロセスのことですか?
だったら、fork()はしないと思いますが・・・。
# ここ、暇なときにDSOの仕組みをもう一度調べて、間違ってたら訂正します。
異なるhttpdに接続されたHTTPセッションは、全く関連性が無いと
思います。
# これも、後日訂正の可能性あり。
0145電動ナナシ
NGNG> fork()って、PHPのプロセスのことですか?
いや、httpd のプロセスのこと。
さっきマニュアル見たらちゃんと書いてあった。httpd の Child Process ごとに
永続的接続するよって。
鬱だし脳。
http://www.php.net/manual/ja/features.persistent-connections.php
0146名無しさん@お腹いっぱい。
NGNG来は英数字のみの組合せ)を入力してもらい、それをPHPを通じてPostgreSQL
からデータをピックアップ予定です。
この$test_idがselect文において
select * from t_test where test_id = $test_id
としてデータをピックアップする際の判断材料です。
しかし、フォームの場合だと何も入力しないで送信したり、2文字
と指定していても1文字しか入れないなど、色々問題が考えられま
すよね?
で、それらはPHP内にエラー処理スクリプトを書いて、自分では
「完璧!」とか思っていたのです。
でも、ちょっと不安だったので、色々とフォームに英数字以外に
記号など(*や!などなど)を入れると、エラーが出ることが判明
しました。
このような記号が入力されたとき、何か上手にエラー対処する方
法などを教えていただけませんでしょうか?
0147名無しさん@お腹いっぱい。
NGNGereg()とかpreg_xxxx()などの正規表現ライブラリ関数を使って、
妥当性チェックしてみてはいかが?
0148146
NGNG早速ereg("[[:alnum:]]{2}", $test_id)として、ちゃんと指定の
形で英数字2文字だけが入力されているかを判定させてみました。
無事考えていたことが出来ました。
ありがとうございます。
0149名無しさん@お腹いっぱい。
NGNGereg()の正規表現って気持ち悪いね
0150名無しさん@お腹いっぱい。
NGNG149って気持ち悪いね
0151名無しさん@お腹いっぱい。
NGNG>安定性が確認されていないベータ版には興味がないのかもしれないね。
つーか、ほいほい導入してもデータの移行が大変なんだよ
0152名無しさん@お腹いっぱい。
NGNGサイトはありますか?
0153名無しさん@お腹いっぱい。
NGNGどなたかご親切なアドバイスをいただけませんか?
フォームからInsert用のデータを受取り、それを処理するファイルがhoge.php3
とします。
フォームからのデータ自体をphp3利用でPostgreSQLにInsertすることまでは出
来ました。
しかし、このままでは本当にそのデータがちゃんとデータベースに登録されたのかど
うかがフォームに書き込んだ人は判りませんから、同じhoge.php3にデータ登録後
に今度は今ちょうど登録したデータはこれでいした、みたいに表示させたいのです。
でも、それを簡単に処理する方法がどうしても思い付きません。
是非この簡単・初歩の初歩だとは思うのですが、それすら判らない厨房に是非暖かい
アドバイスをいただけませんでしょうか?
0154名無しさん@お腹いっぱい。
NGNG$result = pg_exec($sql);
if($result){
echo "登録したデータは$hoge";
}
0155Error 401
NGNGどこが判らないのかが良くわかりませんが、
pg_getlastoid()
を使えば、pg_exec()でInsertされたオブジェクトのoidを取得できます。これで、
select * from table_name where oid = $last_oid
とすれば、今Instertしたタプル(行)を取り出せます。
それとも、取り出したタプルを簡単に表組して表示する方法がわからない
のかな?
0156名無しさん@お腹いっぱい。
NGNG私もそれでいいと思います。
同時にinsert,selectの部分はトランザクション入れた方がいいかも。
oid取得後selectして、
表組みが面倒ならpg_fetch_array($r,$row)で配列に格納して
テンプレートファイルに埋め込むという手も。
見栄えはいいかも・・。
0157153
NGNG>>155
>>156
皆さん本当にありがとうございます。
PHPの本を買って、色々関数を探してみているのですが、実際にそれ
らをどう活用するのかが今ひとつ理解しきれていません。
今晩家に帰って早速皆様から教えていただきました方法を試してみ
ます。
結果はまた今度お知らせします。
0158PHP-jp観察者
NGNGより引用。
-----------------------------
ってな、環境のシステムのプログラムを引き継ぐ事になってプログラムの改良を
行っているのですが、以下の様なコードで2回目のpg_execで処理が戻るまで
約40分くらい掛かってしまいます。
----------------------------------------------------------------------
$sql1 = "SELECT * FROM usertable WHERE syumi='".$syumi_data."'";
$user = pg_exec($conn, $sql1);
$row = pg_numrows($user);
$temp = "user_id in ('".pg_result($user, 0, user_id);
for ($j = 1; $j < $row; $j++) {
$temp = $temp."','".pg_result($user, $j, "user_id");
}
$temp = $temp."')";
$sql2 = "SELECT * FROM maintable WHERE ".$temp." ORDER BY user_id";
if (false == ($main = pg_exec($conn, $sql2))) {
echo "検索失敗";
return false;
} else {
echo "検索完了";
}
----------------------------------------------------------------------
原因は、前のpg_execで見つけてきたuser_idが7000件近くあって、
-----------------------------
joinを知らない奴、逝ってよし。
しかも質問者は、selectを中止させる or postgresプロセスをkillする
方法を探してるときたもんだ。
0159153
NGNG実は私が質問する際、PHP-jpと2ちゃんねるのどちらで聞こうか
迷いました。
最終的にこちらで教えてくれる人達の方が凄く親切・丁寧である
ような気がして、昨晩書き込みした次第です。
なんだかPHP-jpだと、初心者だと突き放されそうな気がして、ど
うも尻ごみしてしまいます。
0161電動ナナシ
NGNGこれはちょっとショッキングだなあ。
SELECT m.user_id, .... FROM usertable u, maintable m WHERE u.user_id = m.user_id
AND u.syumi = :SYUMI ORDER BY m.user_id;
ってするだけの話だよね。
さっき pgsql にも流れてきたけど、根本的に SQL が分かっていないねえ。
■ このスレッドは過去ログ倉庫に格納されています