web-dev-qa-db-ja.com

PDO ATTR_PERSISTENTを完全に理解する

質問:

PDOを使用する場合の永続的な接続管理の背後にあるルール/ロジックは何ですか?


環境:

Webサーバー

  • Windows 7 x64
  • 16GB RAMのデュアルコア
  • Apache 2.2.17
  • PHP 5.3.5
  • IPアドレス、ポート、サービス名などのDSN文字列を介して接続しています...
  • いいえODBC for DB conn(今すぐ2時間作成しようとしています、Oracleに感謝します!)

DBサーバー

  • Linux上のOracle 10g
  • 4GB RAMのマルチコア
  • 私のWebアプリ専用に作成されたユーザー名(はい、それは偽物です)
    • ユーザー:webuser

私の理解/観察:

非永続的な接続

<?php

// Open a new connection
// Session created in Oracle
$dbh = new PDO('DSN', 'webuser', 'password');

// webuser is active in v$session with a SID=1

$dbh = NULL;

// webuser removed from v$session

// Manually calling $dbh = NULL; will remove the session from v$session
// OR
// Wait for script EOL so a kill-session command is sent to Oracle?

?>
  • フレームワークのオーバーヘッドなどでスクリプトを実行するには、確実に約.09秒かかります。

持続的な接続

<?php

// Open a new connection and make it persistent
// Session created in Oracle
// Is Apache maintaining some sort of keep-alive with Oracle here?
// because I thought php.exe is only alive for the duration of the script
$dbh = new PDO('DSN', 'webuser', 'password', array(PDO::ATTR_PERSISTENT => TRUE));

// webuser is active in v$session with a SID=1

$dbh = NULL;

// webuser is still active in v$session with a SID=1

$dbh = new PDO('DSN', 'webuser', 'password', array(PDO::ATTR_PERSISTENT => TRUE));

// webuser is still active in v$session with a SID=1

// Manually calling $dbh = NULL; does not kill session
// OR
// Script EOL does not kill session
// ^^ this is good, just as expected

?>
  • フレームワークのオーバーヘッドなどで、最初のアクセス時にスクリプトの実行に〜.12秒かかります。
  • 後続の実行は〜.04かかります

問題:

ページにアクセスすると、webuserSID=1を取得します

同僚がページにアクセスし、webuserが追加のSID=2を取得します<-このページにアクセスする新しいコンピューターのSIDをすすぎ、繰り返し、インクリメントします

新しい訪問者がSID=1を再利用するべきではありませんか?


すべての回答、提案、代替テストの要求、資料の閲覧へのリンクを歓迎します。

私はしばらくの間RTFMを行っており、グーグルはわずかなAdvantages of Persistent vs. Non-persistentブログしか作成していません。

23
MonkeyZeus

Apacheの視点

Apacheには1つの親プロセスがあります。このプロセスは、Webサーバーに送信される要求を処理する子プロセスを作成します。 Webサーバーの起動時に開始される子プロセスの初期量は、Apache構成のStartServersディレクティブによって構成されます。この数は、ServerLimitに到達するまで、Webサーバーにヒットするリクエストの量が増えるにつれて、必要に応じて増加します。

PHPと永続的な接続

PHP(CGIはスクリプトの実行の最後にすべてのリソースが解放されるため、mod_phpとして実行されます)が要求に対してデータベースとの永続的な接続を確立するように指示されている場合、この接続は保持されます現在、保持されている接続は、要求が処理されたApache子プロセスとデータベースサーバー間の接続であり、この正確な子プロセスで処理されているすべての要求で再利用できます。

何らかの理由で(理由を正確に尋ねないでください)、子プロセスが実際の要求よりも長く占有されており、別の要求が着信した場合、親Apacheプロセスは、この要求を(確立されていない)新しい子プロセスにリダイレクトします。これまでのデータベースへの接続。スクリプトの実行中に実行する必要がある場合は、観察したとおりにSIDを上げます。これで、Apacheの2つの異なる子プロセスによって保持される2つの接続があります。

それを念頭に置いて...

これは多くの問題を引き起こす可能性があることを知っておくことが重要です。エンドレスループが存在する場合や、トランザクションが中止された場合など、スクリプトの実行中に予期しないエラーが発生した場合、接続はブロックされ、再利用できません。また、データベースで使用可能なすべての接続が使用されている可能性もありますが、データベースにアクセスしようとしているApacheサーバーの別の子プロセスがあります。このプロセスは、接続がデータベースまたはApacheによって解放されるまで(タイムアウトまたは自発的に終了するまで)一時的にブロックされます。このページのこのトピックに関する詳細情報: http://www.php.net/manual/en/features.persistent-connections.php

コメントの会話で話し合ったことをすべて正しくまとめ、何も忘れていないことを願っています。もしそうなら、私にヒントを残してください、私はそれを追加します。 :)

編集:

このコメント で言及されている@MonkeyZeusの記事を読み終えたところです。上記で要約したプロセスを説明し、Apacheサーバーを最適化して永続的な接続と連携させる方法に関する有用な情報を提供します。ただし、Oracleデータベースのバックエンドがあってもなくても使用できます。あなたは一見を与えるべきです: http://www.Oracle.com/technetwork/articles/coggeshall-persist-084844.html

36
func0der

メリット

phpのマニュアルページから this link の永続的な接続について:

持続的接続とは、スクリプトの実行が終了しても閉じないリンクです。永続的な接続が要求されると、PHPは、同じ永続的な接続(以前に開いたままになっている)がすでに存在するかどうかを確認します。存在する場合はそれを使用します。存在しない場合は、リンク。

もちろん、永続的な接続を使用する理由は、かなり高価な接続の数を減らすことです。 MySQLの方が他のほとんどのデータベースよりもはるかに高速ですが。

問題

永続的な接続を使用しているときに テーブルロック にいくつかの問題があります。

なんらかの理由でスクリプトがロックを解除できない場合、同じ接続を使用する後続のスクリプトは無期限にブロックされ、httpdサーバーまたはデータベースサーバーの再起動が必要になる場合があります。

もう1つは、mysql commit でトランザクションを使用する場合です。

トランザクションブロックは、トランザクションブロックが終了する前にスクリプトの実行が終了した場合、その接続を使用する次のスクリプトにも引き継がれます。どちらの場合でも、register_shutdown_function()を使用して簡単なクリーンアップ関数を登録し、テーブルのロックを解除したり、トランザクションをロールバックしたりできます。

永続的な接続の欠点について この質問 を読むことをお勧めします。

4
Amir Fo