LoginSignup
42
43

More than 5 years have passed since last update.

PHPとMysqlのコネクションについて調べてみた

Last updated at Posted at 2016-09-08

トランザクションがコネクション切断時とかに、どういう挙動を示すか?調べてみました。

PHP&MySQLのトランザクション関連の仕様ざっくりと

デフォルトでは、すべてのSQLがトランザクションを使用し、オートコミットする。(updateしたら即反映)

明示的に、beginTransactionした場合、そのコネクション上で行われた更新は、commit or rollbackメソッド実行時に一括で反映される。

また、beginTransaction中に接続が切断された場合、rollbackする。
http://dev.mysql.com/doc/refman/5.6/ja/innodb-implicit-commit.html

他のRDBMSだと、コネクション切断時はデフォルトcommitだったりするときもあるので、挙動は確認したほうが良いと思います。

暗黙的コミットにも気をつける

13.3.3 暗黙的なコミットを発生させるステートメント

create tableなど、発行した時点で、既存トランザクションをcommitしてしまうので、オンラインで扱わないように。。。

PHPでのDB接続は、ラッパーモジュールを通して行う

mysqli、PDO_MySQL、そして mysql といった PHP 拡張モジュールは、Cクライアントライブラリの軽量なラッパーです。

ラッパーモジュールのコンパイル時に、Cのライブラリを指定するようです。デフォルトで同梱されているコンパイル済みモジュールでは、mysqlnd(MySQL Native Driver)が使われています。

一応、libmysqlclientというモジュールもあるようですが、マニュアルには、mysqlndが推しモジュールだと書いてありました。

PHP拡張モジュールmysqliとPDOの違い

MySQL用PHPドライバの概要 - どの API を使うか

ざっくりまとめると、違いは

php_pdo_mysql.dll

  • Laravelはこちらを使用
  • マルチDB対応している
  • サーバーサイドとクライアントサイドのprepared statementが利用可
  • 圧縮プロトコルが利用不可
  • 非同期クエリを利用不可

php_mysqli.dll

  • Mysqlオンリー
  • pdoよりも詳細な指定が出来る
  • サーバーサイドprepared statementのみ
  • 圧縮プロトコルが利用可能
  • 非同期クエリを利用可能

Laravelなどフルスタックフレームワークを使う場合、PDO使われている場合が多いと思います。(マルチDB対応するためそうなっているのかと。)

PHPではコネクションプーリングしない?

Laravelしか見ていないのですが、デフォルトではプーリングしない設定です。(コネクションをリクエスト毎に張って、リクエスト終了後切断する動作をする。)Mysqlの場合、接続コストが低いのと、プーリングしないほうがシンプルだからという話があるようです。
RDBMSでコネクションプールが必要な理由、わからない。

Java&MysqlとNode.js&MongoDBでは、設定部分でpoolingの話が出るので経験上設定するものだと思っていたのですが、PHPではそうでもないようですかね?劇的にパフォーマンスが変わらないなら、設定する必要も無いのでは?というのがファイナルアンサーのようですが。。。

Webシステムにおけるデータベース接続アーキテクチャ概論

コネクションプーリングの実装に習熟する暇がないなら、データベースのスケールアップやスケールアウトで解決するなら、それでよいと思っている。 無理に難しいことをし始めて、トラブルシューティングに時間を浪費してしまうということもある。 MySQLのマスタのスケールアップが限界にきていて、コネクション数の上限にあたりそうな場合や、2~3桁のMySQLのスレーブ数のうち何割か台数を減らせる見込みがあるなら、コネクションプーリングを検討してもよいと思う。

プーリング方法

デフォルトプーリングしないけど調べたので書きます

PDO

$dbh = new PDO($dsn,$user,$password,array(PDO::ATTR_PERSISTENT => true));

Mysqli(Mysqlのみだが、非同期クエリやデータの)

http://php.net/manual/ja/mysqli.real-connect.php
$mysqlhost = "p:192.168.33.50";
$username = "takara";

IPの先頭にp:付ける仕様。分かりづらいですね。。。

Laravelでの指定方法

config\database.php
'mysql' => [
    'driver' => 'mysql',
    'host' => env('DB_HOST', 'localhost'),
    'port' => env('DB_PORT', '3306'),
    'database' => env('DB_DATABASE', 'hoge'),
    'username' => env('DB_USERNAME', 'hoge'),
    'password' => env('DB_PASSWORD', ''),
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
    'options'   => [ // ここの部分!!隠しオプションっぽい。
        PDO::ATTR_PERSISTENT => true,
    ],
],

まとめ

  • PHP&Mysqlの場合、コネクション切断時はrollbackなので大丈夫そう。
  • 暗黙的なコミットを発生させるステートメントには気をつける
  • 計測して価値がありそうならプーリングする
42
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
43