MySQL 5.7でクライアントプログラムがCPUを食いつぶす件

同根のバグレポートが散見されますが、ここ数ヶ月、状況をみるに修正される見込みがなさそうなので記録しておきます。

事象

MySQL 5.7 の libmysqlclient (libmysqlclient.so.20) を使用しているプロセスが、無限ループに突入して CPU (user%) を食いつぶし続ける。

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
28150 hirose31  20   0   32488   6080   5492 R  93.8  0.3   0:16.70 mysql

発現条件

MySQLが提供しているパッケージのMySQL 5.7.25, 5.7.26, 5.7.27 で確認。

再現手順

  1. mysql_real_connect() でサーバーに接続する
    • その際に以下の条件を満たすこと
    • reconnect option を有効にしない
    • TCP で接続する(unix domain socket では再現しない)
    • 同じホストの mysqld に接続する
  2. なんらかのシグナルを受信する
  3. mysqld サーバー側からコネクションを切断する
    • 例えば以下のようにして切断する
    • wait-timeout を超過する
    • mysqld を停止する
  4. mysql_real_query() もしくは mysql_ping() が呼ばれる
  5. 無限ループに突入して CPU (user%) を食いつぶす

なお、MySQL 5.6 (libmysqlclient 18) や MySQL 8.0 (libmysqlclient 21) では発生しない。原因は yaSSL にあるのだけど、MySQL 8.0 は yaSSL ではなく OpenSSL を使っているので。

再現コード

回避方法

MySQL サーバーの my.cnf の [mysqld] グループに skip-ssl と書く。

# /etc/my.cnf
[mysqld]
...
skip-ssl
...

追記 2019-11-22

SSL の実装はソースツリー内にある yaSSL と OpenSSL とで選択できたのですが、MySQL 5.6.46, 5.7.28 から yaSSL が削除され OpenSSL のみとなりました。

当然、バイナリで配布されているパッケージも OpenSSL を使うようにビルドされています。そこで 5.7.28 で試したところ、問題が再現しないことが確認できました。