../ |
---|
CentOS Stream 8でPHP7.4からPDOでMySQL8.0に接続する際に「Packets out of order. Expected 1 received 0」のワーニングが出る時がある。毎回確実に出る訳でもなく、どのような状況の時に出るのかは判明できていない。心当たりのある原因を後述しておく。
PHP message: @@ enter getUsers('admin',false)
PHP message: @@ new UserManager()
PHP message: @@ new UserDataAccessor()
PHP message: @@ PersistenceBase::__construct()
PHP message: @@ PersistenceBase::pdo = null
PHP message:
PHP Warning: Packets out of order. Expected 1 received 0. Packet size=145
in common/integration/PersistenceBase.php on line 46
PHP message: @@@ connected mysql:dbname=test;host=localhost;port=3306;charset=utf8
PHP message: @@@ select * from user order by user_id --> 6
数日前は何度か起きていたが、最近はまったく起きていない。
上記の場合、PDOに接続でき、ユーザー情報の検索はできている。PDOに接続に行く際に「Packets out of order. Expected 1 received 0」のWarningが出たと言っている。「パケットの順序がおかしい。1でないといけないのに0になっている」と言っている。Warningだから無視していいのか、解決すべきなのかも分からず。
private function pdo(): PDO {
error_log('@@ PersistenceBase::pdo = ' . (is_null($this->pdo)? 'null' : 'available'));
if (empty($this->pdo)){
$dsn = $this->props['db.dsn'];
$user = $this->props['db.user'];
$password = $this->props['db.password'];
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
// PDO::ATTR_EMULATE_PREPARES, false,
PDO::ATTR_PERSISTENT => true
];
try {
$this->pdo = new PDO($dsn, $user, $password, $options);
error_log("@@@ connected " . $dsn);
} catch (PDOException $e) {
error_log("@@@ dsn = " . $dsn);
error_log("@@@ user = " . $user);
error_log("@@@ password = " . $password);
error_log("@@@ connect failed: " . $e->getMessage());
error_log($e->getTraceAsString());
}
}
return $this->pdo;
}
ネット情報を見てもよく分からず。再現するようになったら、そのとき再度、調べたい。関連しそうなログは、以下のもの。
$ tail -200 /var/log/php_errors.log
$ tail -200 /var/log/httpd/error_log
$ tail -200 /var/log/mysql/mysqld.log
$ tail -200 /var/log/nginx/error.log
$ tail -200 /var/log/php-fpm/error.log
原因は、MySQLの wait_timeout が8時間の問題だったかも
確認はしていないのだけど、原因は、MySQLの wait_timeout の設定だったかもしれない。MySQLは、デフォルトでは8時間アクセスがないとタイムアウトする。例えば、前日にはうまく行っていても、翌朝にはMySQLを再起動しないといけないときが、Javaでもあった。今回の環境でも、wait_timeoutを設定しないまま使っていたためかもしれない。
以下のように、wait_timeout に31536000をセットしたから起きなくなったのかな。31536000 = 365 * 24 * 3600 である。
$ vi /etc/my.cnf.d/mysql-server.cnf
[mysqld]
character-set-server=utf8
lower_case_table_names=1
interactive_timeout=31536000
wait_timeout=31536000
PHPのシステムロガー error_log() の使い方
ついでなので、PHPのシステムロガーの使い方を整理しておく。呼び出しには、汎用のerror_log()を使う。
error_log(string $message, int $message_type = 0, ?string $destination = null): bool
message_type=0のとき、message がPHPのシステムロガーに送られ、error_log の値に応じて、OSのシステムログ機構を使って保存されるか、ファイルに保存されるかが決まる。デフォルトのオプション。
message_type=3のとき、message は destination で指定されたファイルに追加される。messageの末尾に改行文字を付与した方がよい。
PHPのシステムロガーの設定は、php.ini で行う。
$ vi /etc/php.ini
; 出力するエラーのレベル
;error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
error_reporting = E_ALL
; エラーを表示するか。どこに表示するか。{ On,Off,stderr,stdout }
display_errors = On
; 起動時のエラーを表示するか。
display_startup_errors = On
; ログを出力するか。stderrやerror_logで指定される場所に出力される。
log_errors = On
; ログの出力先ファイル
error_log = /var/log/php_errors.log
; ログの出力先をsyslogに委ねる場合
;error_log = syslog
;syslog.ident = php
;syslog.facility = user
$ systemctl restart httpd
$ systemctl restart nginx
以前は、error_reporting = E_ALL | E_STRICT と書いていたらしい。PHP7.4では error_reporting = E_ALL でいい。E_STRICTなど細かいものを除外するときは、error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT と書くそうだ。
../ |
---|