PHP 8.3.4 Released!

データベース接続

MySQL は、サーバーに接続するために、 異なるトランスポート層をサポートしています。 TCP/IP, Unix ドメインソケット、 そして、Windows の名前付きパイプです。

ホスト名 localhost には特別な意味があります。 これは、Unixドメインソケットにバインドされます。 localhost に対して TCP/IP 接続を開くには、 localhost の代わりに、 127.0.0.1 を使わなければいけません。

例1 localhost が持つ特別な意味

<?php

$mysqli
= new mysqli("localhost", "user", "password", "database");

echo
$mysqli->host_info . "\n";

$mysqli = new mysqli("127.0.0.1", "user", "password", "database", 3306);

echo
$mysqli->host_info . "\n";

上の例の出力は以下となります。

Localhost via UNIX socket
127.0.0.1 via TCP/IP

デフォルトの接続パラメータ

接続関数によっては、 引数を省略できる場合があります。 引数が与えられない場合、 拡張モジュールは PHP の設定ファイルに設定されたデフォルト値を使おうとします。

例2 デフォルト値を設定する

mysqli.default_host=192.168.2.27
mysqli.default_user=root
mysqli.default_pw=""
mysqli.default_port=3306
mysqli.default_socket=/tmp/mysql.sock

結果として決まった引数の値が、 拡張モジュールが使うクライアントライブラリに渡されます。 クライアントライブラリが空、または未設定の引数を検知した場合、 ライブラリに組み込まれたデフォルト値が使われます。

ライブラリに組み込まれたデフォルト値

host の値が未設定または空の場合、 クライアントライブラリはデフォルト値を Unixドメインソケットの localhost とします。 socket の値が未設定または空の場合、 かつ Unixドメインソケットの接続がリクエストされた場合、 デフォルトのソケット /tmp/mysql.sock を使って接続を試みます。

Windows の場合、 ホスト名 . は、クライアントライブラリによって Windows の名前付きパイプベースの接続をオープンするものと解釈されます。 この場合、socket のパラメータはパイプの名前として解釈されます。 この値が未設定または空の場合、 ソケット(パイプ名)のデフォルトは \\.\pipe\MySQL となります。

Unixドメインソケットベース、 および Windows の名前付きパイプベースの接続が両方確立されず、 port パラメータが未設定の場合、 ライブラリはデフォルトのポートを 3306 に設定します。

mysqlnd ライブラリと MySQL Client Library (libmysqlclient) は、 デフォルト値を決めるためのロジックは同じです。

接続オプション

接続オプションも利用可能です。 たとえば、接続時に実行される初期化コマンドや、 特定の文字セットを使うようにリクエストするなど、です。 接続オプションはネットワーク接続が確立される前に設定しなくてはいけません。

接続オプションを設定するために、 接続操作は3つの段階を踏んで行われます。 mysqli_init() または mysqli::__construct() を使って接続ハンドルを初期化し、 mysqli::options() を使って リクエストされた接続オプションを設定し、 mysqli::real_connect() で、ネットワーク接続を確立します。

接続のプーリング

mysqli 拡張モジュールは、 データベースへの持続的接続をサポートしています。 これは、特別な種類の接続で、プーリングされます。 デフォルトでは、 スクリプトによってオープンされたデータベース接続それぞれが、 ユーザによって明示的に閉じられるか、 スクリプトによって自動的に開放されます。 持続的接続はそうではなく、 開放する代わりに、後に再利用するためにプールに戻します。 同じサーバーへの接続が同じユーザ名、 パスワード、ソケット、ポート、 そしてデフォルトデータベースを指定してオープンされた場合、 接続が再利用され、接続のオーバーヘッドが軽減されます。

PHP のプロセスごとに、mysqli の接続プールが使われます。 webサーバーがどのように運用されるかによりますが、 PHP のプロセスはひとつ以上のリクエストを処理する可能性があります。 よって、プーリングされた接続は ひとつ以上のスクリプトから後に使われる可能性があるのです。

持続的接続

あるホスト名、ユーザ名、パスワード、ソケット、ポート、 そしてデフォルトのデータベースの組み合わせについて、 未使用の持続的接続がプールに見つからない場合、 mysqli は新しい接続をオープンします。 持続的接続を使うかどうかは、 mysqli.allow_persistent を使って制御できます。 スクリプトがオープンする接続の合計数は、 mysqli.max_links で制御できます。 PHP プロセス毎に使う持続的接続の最大数は mysqli.max_persistent で制御できます。 Webサーバーは多くの PHP プロセスをforkさせる可能性があることに注意して下さい。

持続的接続についてよくある不満が、 再利用する前にステートがリセットされないというものです。 たとえば、 オープンされ、終了していないトランザクションは 自動的にロールバックされません。 しかし同時に 接続をプールに戻し、 再利用するまでの間に行われた認証情報の変更も反映されません。 これは、望ましくない副作用と見なされるかもしれません。 一方で、persistent という名前は、 ステートを維持することを約束していると理解されるかもしれません。

mysqli 拡張モジュールは、 持続的接続について、両方の解釈をサポートしています: ステートを維持するか、 再利用する前にステートをリセットするか、です。 デフォルトはリセットです。 持続的接続が再利用される前に、 mysqli 拡張モジュールは暗黙のうちに ステートをリセットするために mysqli::change_user() をコールします。 持続的接続は、 これによってちょうど今オープンされたかのようにユーザの前に出現します。 以前利用されていた状態は見えません。

mysqli::change_user() をコールすると、コストが高く付きます。 パフォーマンスを最大にするために、 ユーザーはコンパイルフラグ MYSQLI_NO_CHANGE_USER_ON_PCONNECT を設定して、拡張モジュールをリコンパイルしたいかもしれません。

安全な振る舞いと、 最大のパフォーマンスのどちらを取るかは、 ユーザに任されています。 どちらを選んでも、最適化の目的としては正当なものです。 使いやすさを求めれば、 パフォーマンスを犠牲にして安全な振る舞いを行わせる ことがデフォルトになります。

参照

add a note

User Contributed Notes 1 note

up
-36
xylene2301 at gmail dot com
1 year ago
"The hostname localhost has a special meaning. It is bound to the use of Unix domain sockets. To open a TCP/IP connection to the localhost, 127.0.0.1 must be used instead of the hostname localhost."

Is there something I missed or is this 1st provision incorrect?
On windows11, using PHP 7.4 and MySQL 8,

$conn = new mysqli("localhost", "root", "pword", "tstDB");
echo $conn->host_info . "\n";

returns:
localhost via TCP/IP Connected to the database.
To Top