この記事では、PHP におけるデータベース接続の永続性について詳しく説明します。一定の参考値があるので、困っている友達が参考になれば幸いです。
データベースの最適化は Web 開発における最優先事項であり、多くの場合、実際にデータベース用にプログラミングを行っています。もちろん、ユーザーの操作や行動はすべてデータとして保存されます。
このうち、データベース接続作成プロセスで最適化できるものはありますか?答えはもちろん「はい」です。Java などの言語には接続プールの設定がありますが、PHP には通常の開発では接続プールのようなものはありません。接続プール技術はマルチスレッドが関与する場合によく使用されるため、PHP は実行するたびに新しい接続が作成されます。この場合、データ接続を最適化するにはどうすればよいでしょうか?
まず、データベース接続の永続性の定義を見てみましょう。
永続的なデータベース接続とは、スクリプトの実行終了時に閉じられない接続を指します。永続的な接続要求を受信したとき。 PHP は、(以前に開かれた) 同一の永続接続が既に存在するかどうかを確認します。
存在する場合はこの接続が直接使用され、存在しない場合は新しい接続が確立されます。いわゆる「同じ」接続とは、同じユーザー名とパスワードを使用した同じホストへの接続を指します。
Web サーバーの動作と分散負荷を完全に理解していない読者は、永続的な接続の役割を誤解する可能性があります。特に、永続的な接続は、同じ接続上で「ユーザー セッション」を確立する機能を提供せず、トランザクションを効果的に確立する機能も提供しません。実際、厳密に言えば、永続接続は、非永続接続が提供できない特別な機能を提供しません。
これは PHP における接続の永続性ですが、永続的な接続には非永続的な接続では提供できない特別な機能がないことも指摘しています。非常にややこしいのですが、この解決策でパフォーマンスが向上すると言われているのではないでしょうか?
はい、上記の定義で指摘された特別な機能から判断すると、永続的接続は新しい機能やより高度な機能をもたらしませんが、その最大の用途は効率を向上させることであり、パフォーマンスも向上することを意味します。
Web サーバーから SQL サーバーへの接続コスト (オーバーヘッド) が高い場合 (たとえば、時間がかかり、一時メモリの消費量が多くなる場合)、永続的な接続の方が効率的になります。
つまり、接続コストが高い場合、データベース接続を作成するコストも大きくなり、当然時間も長くなります。永続的な接続を使用した後、各子プロセスは、ページを処理するたびに SQL サーバーに接続要求を行うのではなく、ライフ サイクルで 1 回だけ接続操作を実行します。これは、各子プロセスがサーバーへの独自の独立した永続的な接続を確立することを意味します。
たとえば、20 の異なる子プロセスが永続的な SQL サーバーの永続接続を確立するスクリプトを実行すると、実際には SQL サーバーに対して 20 の異なる永続接続がプロセスごとに 1 つずつ確立されます。
さっそく、コードを通して直接比較してみましょう。まず、現在のミリ秒時間を返す統計関数を定義します。さらに、データ接続パラメータも準備する必要があります。
function getmicrotime() { list($usec, $sec) = explode(" ", microtime()); return ((float) $usec + (float) $sec); } $db = [ 'server' => 'localhost:3306', 'user' => 'root', 'password' => '', 'database' => 'blog_test', ];
次に、まず通常の mysqli をテストに使用します。
$startTime = getmicrotime(); for ($i = 0; $i < 1000; $i++) { $mysqli = new mysqli($db["server"], $db["user"], $db["password"], $db["database"]); //持久连接 $mysqli->close(); } echo bcsub(getmicrotime(), $startTime, 10), PHP_EOL; // 6.5814000000
1000 サイクルにわたるデータベース接続の作成プロセスで、6 秒以上かかりました。次に、永続的な接続を使用して、これら 1,000 のデータベース接続を作成します。 mysqli の $host パラメータの前に p: を追加するだけです。
$startTime = getmicrotime(); for ($i = 0; $i < 1000; $i++) { $mysqli = new mysqli('p:' . $db["server"], $db["user"], $db["password"], $db["database"]); //持久连接 $mysqli->close(); } echo bcsub(getmicrotime(), $startTime, 10), PHP_EOL; // 0.0965000000
mysqli 接続の観点から見ると、効率の向上は明らかです。もちろん、PDO データベース接続には、永続的な接続を確立する特性もあります。
$startTime = getmicrotime(); for ($i = 0; $i < 1000; $i++) { $pdo = new PDO("mysql:dbname={$db['database']};host={$db['server']}", $db['user'], $db['password']); } echo bcsub(getmicrotime(), $startTime, 10), PHP_EOL; // 6.6171000000 $startTime = getmicrotime(); for ($i = 0; $i < 1000; $i++) { $pdo = new PDO("mysql:dbname={$db['database']};host={$db['server']}", $db['user'], $db['password'], [PDO::ATTR_PERSISTENT => true]); //持久连接 } echo bcsub(getmicrotime(), $startTime, 10), PHP_EOL; // 0.0398000000
PDO モードで接続する場合は、PDO::ATTR_PERSISTENT パラメーターを指定して true に設定する必要があります。このようにして、PDO によって確立された接続も永続的な接続になります。
データベースの永続的接続は非常に強力なので、この永続的接続フォームをデフォルトにしないのはどうでしょうか。これを実現するにはパラメータを手動で追加する必要がありますか? ? PHP 開発者は確かに依然として懸念を抱いています。
永続的な接続を持つ子プロセスの数がデータベース接続数に設定された制限を超えると、システムで問題が発生します。データベースの同時接続数が 16 に制限されており、ビジー セッションの場合に 17 のスレッドが接続を試行すると、1 つのスレッドが接続に失敗します。このとき、接続を閉じることを妨げるエラー (無限ループなど) がスクリプト内で発生すると、データベースへの 16 個の接続がすぐに影響を受けます。
同時に、テーブルのロックとトランザクションにも注意が必要です。
永続的な接続でデータ テーブル ロックを使用する場合、スクリプトが何らかの理由でデータ テーブル ロックを解放できない場合、同じ接続を使用する後続のスクリプトは永久にブロックされ、httpd サービスまたはデータベースの再起動が必要になります。 。 仕える###
在使用事务处理时,如果脚本在事务阻塞产生前结束,则该阻塞也会影响到使用相同连接的下一个脚本
所以,在使用表锁及事务的情况下,最好还是不要使用持久化的数据库连接。不过好在持久连接和普通连接是可以在任何时候互换的,我们定义两种连接形式,在不同的情况下使用不同的连接即可解决类似的问题。
事物总有两面性,持久连接一方面带来了效率的提升,但另一方面也可能带来一些业务逻辑上的问题,而且这种问题如果在不了解持久连接的机制的情况下会非常难排查。因此,在日常开发中我们一定要在了解相关功能特性的情况下再选择适合的方式来完成所需要的功能开发。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202004/source/PHP%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%8C%81%E4%B9%85%E5%8C%96.php
推荐学习:php视频教程
以上がPHP におけるデータベース接続の永続性の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。