トランザクションがコネクション切断時とかに、どういう挙動を示すか?調べてみました。
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だったりするときもあるので、挙動は確認したほうが良いと思います。
暗黙的コミットにも気をつける
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ではそうでもないようですかね?劇的にパフォーマンスが変わらないなら、設定する必要も無いのでは?というのがファイナルアンサーのようですが。。。
コネクションプーリングの実装に習熟する暇がないなら、データベースのスケールアップやスケールアウトで解決するなら、それでよいと思っている。 無理に難しいことをし始めて、トラブルシューティングに時間を浪費してしまうということもある。 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なので大丈夫そう。
- 暗黙的なコミットを発生させるステートメントには気をつける
- 計測して価値がありそうならプーリングする