mirror of
https://github.com/php/doc-ja.git
synced 2026-03-23 22:52:11 +01:00
251 lines
13 KiB
XML
251 lines
13 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- $Revision$ -->
|
||
<!-- EN-Revision: cd8b964b8566801265f0d287db6eb651f93be950 Maintainer: mumumu Status: ready -->
|
||
<chapter xml:id="features.persistent-connections" xmlns="http://docbook.org/ns/docbook">
|
||
<title>持続的データベース接続</title>
|
||
|
||
<simplesect>
|
||
<title>持続的データベース接続って何?</title>
|
||
<simpara>
|
||
持続的接続は、スクリプトの実行終了時にも閉じられないリンクです。
|
||
持続的接続が要求された時、
|
||
PHP は(前もってオープンされたままになっている)
|
||
同じ持続的接続が既にオープンされていないかどうかを確認します。
|
||
そして、存在する場合には、それを使用します。存在しない場合には、
|
||
そのリンクを作成します。'同じ'接続とは、同じホスト、同じユーザー名、
|
||
同じパスワード(利用可能な場合)でオープンされた接続のことを意味します。
|
||
</simpara>
|
||
<simpara>
|
||
特定の接続を要求する方法はありませんし、
|
||
既存の接続と新しい接続のどちらを取得できるかを保証する方法もありません。
|
||
(すべての接続が使用中の場合や、
|
||
リクエストが別の接続プールを持つ、
|
||
別のワーカーによって処理される場合があります)
|
||
</simpara>
|
||
<simpara>
|
||
つまり、PHP の持続的接続が使えない場合があるということです。
|
||
たとえば以下の場合です:
|
||
</simpara>
|
||
<simplelist>
|
||
<member>特定のデータベースセッションを、特定のWebユーザーに割り当てる場合</member>
|
||
<member>複数のリクエストにまたがる、巨大なトランザクションを生成する場合</member>
|
||
<member>あるリクエストでクエリを発行し、クエリの結果を別のリクエストで収集する場合</member>
|
||
</simplelist>
|
||
<simpara>
|
||
持続的接続は、
|
||
持続的でない接続にできない機能は <emphasis>全く</emphasis>
|
||
提供しません。
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.web">
|
||
<title>Webリクエスト</title>
|
||
<simpara>
|
||
Webサーバーを PHP と統合し、Webページを生成させる方法はふたつあります:
|
||
</simpara>
|
||
<simpara>
|
||
最初は、CGI "ラッパー"としてPHPを使用する方法です。このように実行した場合、
|
||
PHP インタプリタのインスタンスは、Webサーバーに(PHPページに関する)
|
||
ページがリクエストされる度に生成され、破棄されます。
|
||
リクエスト毎に破棄されるために、(SQLデータベースサーバーへのリンクのような)
|
||
必要な全てのリソースは破棄される際にクローズされます。この場合、
|
||
持続的接続を使用することから得るものは何もありません。
|
||
持続的接続は持続しないのです。
|
||
</simpara>
|
||
<simpara>
|
||
2番目は、最も一般的ですが、PHP を PHP-FPM か、
|
||
マルチプロセスWebサーバー(現在はApacheのみが含まれます)のモジュールとして実行する方法です。
|
||
マルチプロセスサーバーは、通常、
|
||
実際にWebページを送信する複数のプロセス(子)を管理するプロセス(親)を有しています。
|
||
リクエストがクライアントから来ると、
|
||
親プロセスは、
|
||
他のクライアントにすでに送信を行っていないクライアントの一つに渡します。
|
||
このため、
|
||
同じクライアントが2番目のリクエストをサーバーに送信した際に最初のではなく他の子プロセスにより送信が行われる可能性があります。
|
||
持続的接続がオープンされているとき、
|
||
SQL サービスにリクエストを行うそれぞれのページは、
|
||
SQL サーバーへの確立された接続を再利用することができます。
|
||
</simpara>
|
||
<note>
|
||
<para>
|
||
Webリクエスト で使用されているメソッドを確認するには、
|
||
<function>phpinfo</function> の出力における "Server API" の値、
|
||
または Webリクエスト から実行した <constant>PHP_SAPI</constant>
|
||
の値を確認してください。
|
||
</para>
|
||
<para>
|
||
サーバーAPI が "Apache 2 Handler" や "FPM/FastCGI" の場合、
|
||
持続的接続は同じワーカーで処理されるリクエスト間で使われます。
|
||
これら以外の値の場合、
|
||
持続的接続はそれぞれのリクエストを処理したあとは持続しません。
|
||
</para>
|
||
</note>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.cli">
|
||
<title>コマンドラインのプロセス</title>
|
||
<simpara>
|
||
コマンドラインから実行する PHP は、
|
||
スクリプトごとに新しいプロセスを使います。
|
||
持続的接続は、コマンドラインから実行するスクリプト間では共有されません。
|
||
よって、cron やコマンドからのような一時的なスクリプトから、
|
||
持続的接続を使ってもなんの役にも立ちません。
|
||
とはいっても、役に立つ場面はあるかもしれません。
|
||
たとえば、たくさんのリクエストや、
|
||
個別のタスクがそれぞれのデータベース接続を必要とする多数のタスクを処理する
|
||
アプリケーションサーバーを書いている場合が挙げられます。
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.why">
|
||
<title>持続的接続をなぜ使うのか?</title>
|
||
<simpara>
|
||
持続的接続は、SQLサーバーへ接続するオーバーヘッドが大きい場合には有効です。
|
||
このオーバーヘッドが実際に大きいがどうかは様々な要因に依存します。
|
||
例えば、データベースの種類、
|
||
Webサーバーが動作するのと同じコンピューターで動作しているか、
|
||
SQLサーバーを動作させているマシンの負荷、等となります。
|
||
肝心なのは、接続のオーバーヘッドが高い場合、
|
||
持続的接続は著しく効果があるということです。
|
||
持続的接続は、
|
||
SQLサーバーへの接続を要求するページをリクエスト毎に処理する代わりに、
|
||
子プロセスが動作中の間一回しかサーバーへの接続を行わないようにします。
|
||
このことは、
|
||
持続的接続をオープンしたプロセス毎に、
|
||
サーバーへの持続的接続をオープンするということになります。
|
||
例えば、
|
||
20の異なった子プロセスがSQLサーバーへの持続的接続を行うスクリプトを実行した場合、
|
||
各子プロセス毎にSQLサーバーへの20の異なった接続が行われます。
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.drawbacks.conn-limits">
|
||
<title>ありうる欠点: 接続数の上限</title>
|
||
<simpara>
|
||
しかし、データベースへの接続数を制限して使用している場合に、
|
||
持続的な子プロセスの接続数がその数を超える場合は、
|
||
持続的接続には気をつけたほうが良い欠点がいくつかあります。
|
||
もしデータベースの同時接続数の制限が16だとして、
|
||
サーバーに多くのアクセスがあったため、
|
||
17個の子プロセスが接続しようとするとそのうちの一つは接続に失敗します。
|
||
もしスクリプトにコネクションをシャットダウンしないようなバグ(例えば無限ループ)があると、
|
||
16程度の同時接続しか許容しないデータベースはすぐにダメになってしまいます。
|
||
</simpara>
|
||
<simpara>
|
||
持続的接続は通常、特定の時点で開く接続数を増加させます。
|
||
これはアイドル状態のワーカーが、
|
||
以前処理したリクエスト用の接続を保持し続けるためです。
|
||
リクエストの急増に対応するために多数のワーカーが起動された場合、
|
||
それらのワーカーが開いた接続は、
|
||
ワーカーが終了するかデータベースサーバーが接続を閉じるまで残ります。
|
||
</simpara>
|
||
<simpara>
|
||
データベースサーバーが許可する最大接続数が、
|
||
Webリクエストワーカーの最大数(それに cronジョブや、
|
||
管理接続などのその他の使用分を加えた数)よりも大きいことを確認してください。
|
||
</simpara>
|
||
<simpara>
|
||
放棄された接続や、アイドル状態の接続(タイムアウト)の処理方法について、
|
||
データベースのドキュメントで確認してください。
|
||
タイムアウトを長く設定すると、
|
||
同時に開かれる持続的接続の数が大幅に増加する可能性があります。
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.drawbacks.state">
|
||
<title>ありうる欠点: 接続の状態管理</title>
|
||
<simpara>
|
||
一部のデータベース拡張モジュールは、
|
||
接続が再利用される際にクリーンアップを自動的に実行します。
|
||
このクリーンアップのタスクを、
|
||
アプリケーション開発者の裁量に委ねる拡張モジュールもあります。
|
||
選択したデータベース拡張モジュールとアプリケーション設計によっては、
|
||
スクリプト終了前に手動でのクリーンアップが必要になる場合があります。
|
||
接続を予期しない状態に陥らせる可能性のある変更には以下が含まれます:
|
||
</simpara>
|
||
<simplelist>
|
||
<member>データベースの選択 / デフォルトのデータベース</member>
|
||
<member>テーブルロック</member>
|
||
<member>未コミットのトランザクション</member>
|
||
<member>一時テーブル</member>
|
||
<member>プロファイリングのような、特定の設定や機能を有効にした接続</member>
|
||
</simplelist>
|
||
<simpara>
|
||
クリーンアップが行われていない、
|
||
または閉じられていないテーブルロックやトランザクションは、
|
||
他のクエリが無限にブロックされる原因となるほか、
|
||
その後の接続の再利用によって予期しない変更が生じる可能性があります。
|
||
</simpara>
|
||
<simpara>
|
||
誤ったデータベースが選択されている場合、
|
||
その後の接続の再利用ではクエリが期待通りに実行できなくなります
|
||
(スキーマが十分に類似している場合、
|
||
誤ったデータベース上でクエリが実行される可能性があります)。
|
||
</simpara>
|
||
<simpara>
|
||
一時テーブルがクリーンアップされない場合、
|
||
後続のリクエストでは同じテーブルを再作成できません。
|
||
</simpara>
|
||
<simpara>
|
||
クリーンアップは、クラスのデストラクタまたは
|
||
<function>register_shutdown_function</function>を使用して実装できます。
|
||
また、クリーンアップの機能を組み込んだ、
|
||
専用の接続プールプロキシの使用も検討するとよいでしょう。
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.final-words">
|
||
<title>おわりに</title>
|
||
<simpara>
|
||
既に述べた持続的接続の振る舞いと、あり得る欠点を考慮すると、
|
||
持続的接続を使う場合は、必ず慎重に検討を行うべきです。
|
||
持続的接続を使う場合は、
|
||
アプリケーションを追加で変更し、
|
||
データベースサーバーとWebサーバーおよび/またはPHP-FPMを慎重に設定すべきです。
|
||
</simpara>
|
||
<simpara>
|
||
サーバーへ接続するオーバーヘッドの原因を調査・修正する別の代替案
|
||
(例:データベースサーバーへのDNS逆引きの無効化)や、
|
||
専用の接続プールプロキシを検討してください。
|
||
</simpara>
|
||
<simpara>
|
||
高トラフィックのWeb APIについては、代替のランタイムや、
|
||
長時間実行可能なアプリケーションサーバーの使用を検討してください。
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect role="seealso" xml:id="persistent-connections.seealso">
|
||
&reftitle.seealso;
|
||
<simplelist>
|
||
<member><function>ibase_pconnect</function></member>
|
||
<member><function>oci_pconnect</function></member>
|
||
<member><function>odbc_pconnect</function></member>
|
||
<member><function>pfsockopen</function></member>
|
||
<member><function>pg_connect</function></member>
|
||
<member><link linkend="mysqli.persistconns">MySQLi and Persistent Connections</link></member>
|
||
<member><link linkend="pdo.connections">PDO Connection Management</link></member>
|
||
</simplelist>
|
||
</simplesect>
|
||
</chapter>
|
||
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|