Laravel5.2とmysqlnd_msを併用するとSegmentation faultで死亡

透過的にRW Splittingが実現できるという触れ込みのmysqlnd_msを既存アプリの構成に組み込んでみたところ、下記のようなログを残して死亡していた。

child pid 10815 exit signal Segmentation fault (11)

その原因の(ある程度)切り分けと対策メモ。

環境

  • Laravel: 5.2.12
  • mysqlnd_ms: 1.6
  • php: 5.6.18
  • mysqld: 5.6.29

原因

実はLaravelはあまり原因とは関係なく、PDOのコンストラクタでPDO::ATTR_EMULATE_PREPARES => falseを渡すと死亡する模様。 そして、LaravelのPDOのデフォルトオプションはPDO::ATTR_EMULATE_PREPARES => falseです。

対策

サーバサイドのプリペアドステートメントは諦めてPDO::ATTR_EMULATE_PREPARES => trueにする。 Laravelだと下記のように設定する。

        'mysql' => [
            'read' => [
              'host' => env('DB_HOST', 'localhost'),
            ],
            'write' => [
              'host' => env('DB_HOST', 'localhost'),
            ],
            'driver'    => 'mysql',
            'host'      => env('DB_HOST', 'localhost'),
            'database'  => env('DB_DATABASE', 'forge'),
            'username'  => env('DB_USERNAME', 'forge'),
            'password'  => env('DB_PASSWORD', ''),
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
            'strict'    => true,
            'options' => [
                PDO::ATTR_EMULATE_PREPARES => true, // <-- add
            ]
        ],