PHP のバージョンなど。
PHP 5.6.0 / mysqlnd 5.0.11-dev
実行したコード。
<?php
$dsn = 'mysql:host=127.0.0.1;dbname=test;charset=utf8';
$pdo = new PDO($dsn, "test", "pass", array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
));
$pdo->exec("select 1 from dual");
$pdo->exec("select 2 from dual");
発生した例外。
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.'
このエラーには見覚えがあります、PDO::MYSQL_ATTR_USE_BUFFERED_QUERY = 0
なときに複数の結果セットを開くと発生します。
が、PDO::MYSQL_ATTR_USE_BUFFERED_QUERY = 1
などとしても解決しません。
<?php
$dsn = 'mysql:host=127.0.0.1;dbname=test;charset=utf8';
$pdo = new PDO($dsn, "test", "pass", array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => 1,
));
$pdo->exec("select 1 from dual");
$pdo->exec("select 2 from dual");
おそらく PDO::exec()
した後に mysql_store_result()
も mysql_use_result()
も呼ばれていないために結果セットが閉じられておらず、後続の SQL が実行できないのだと思います。
なお、このとき MySQL のエラーログには次が出力されていました。
[Warning] Aborted connection 36 to db: 'test' user: 'test' host: '127.0.0.1' (Got an error reading communication packets)
これは mysql_close
せずにクライアントプロセスを殺すと発生します。つまり接続が正しく閉じられていないので mod_php や fpm だとリークしてそうです。 MySQL への接続はリークしていませんでした。
下記のように PDO の中身が libmysql の場合は MySQL のエラーログにはなにも記録されませんでした。
PHP 5.6.0 / libmysql 5.6.20
PDO::exec()
で select
したのが間違いだと思うので、PDO_MySQL のバグなのかどうかは微妙。。。