エンタープライズIT系エンジニアのぼやっきー

特にまとまりもなく、色々なことをぼやきます。最近はオープンソースの業務系システムに興味あり。

MySQL 5.7.10 の導入は見送ります

MySQL 5.7 になってからオプティマイザが賢くなったとか、かなりの期待感を持っていたため、ローカルや本番用のサーバに入れて検証をしてみました。

結論から言えば、MySQL 5.6 からデグレしています。
ちなみに、全く別件の障害対応に追われているため、原因調査はできていません・・・。

環境

  • MySQL 5.7.10
  • MySQL 5.6.27 (5.7固有の問題か切り分けるために使用)

MySQL 5.7.10の問題は MacOS 10.11.1 と CentOS 7 の両方で確認。

問題1 MySQLのサービスが応答を返さなくなる

  • 10テーブル(それぞれ数百万〜数十万件)に対してDelete文を発行
  • 結果は数件削除(正しい結果)
  • その後から他の接続が全くできなくなる【謎】
  • サービスを再起動して、復旧

データを復元して同じクエリを流すと再現します。
また、Delete文だけでなく、Insertや大量にデータがヒットするSelectでも再現。

特徴といえば、それぞれのテーブルがパーティショニングされていることでしょうか・・・。

MySQL 5.6 では再現せず。

問題2 PKを条件に含むexists句の挙動がおかしい

SELECT
  A.*,
  B.ID,
  B.NAME,
  B.HOGE,
  C.ID,
  C.NAME,
  C.HOGE
FROM
  A
  LEFT OUTER JOIN B ON (B.A_ID = A.ID AND B.USER_ID = ?)
  LEFT OUTER JOIN C ON (C.A_ID = A.ID)
WHERE
  (
    EXISTS(
      SELECT
        1
      FROM
        D
      WHERE
        D.A_ID = A.ID AND
        D.USER_ID = ?
    ) OR
    EXISTS(
      SELECT
        1
      FROM
        E
      WHERE
        E.A_ID = A.ID AND
        EXISTS(
          SELECT
            1
          FROM
            F
          WHERE
            F.E_ID = E.ID AND
            F.USER_ID = ?
        )
    )
  ) AND
  A.ID = ?

※実際にシステムが流したクエリに基づくため、違和感を覚えると思いますが、とりあえず事実を伝えたいのでこれで。

参照権限のチェックをクエリで表現してしまったため、ずいぶんと変なクエリですが、これを実行すると対象レコードが存在するにもかかわらず結果が0件になることがあります。
また、最後の「A.ID = ?」でPrimary Keyを条件にしていること問題のようで、「A.NAME = ?」にして完全一致で名前を入れると対象レコードが取得できます。

面白いのは「D.A_ID = A.ID」のようになっているところを「D.A_ID = ?」などにして「A.ID = ?」で指定している値を入れるとレコードが取得できます。

explainを取っていないとわかりませんが、実行順序で何か問題が起こっているものと思われます。
当然、MySQL 5.6 では再現せず。

# そもそもそんな複雑なクエリをMySQLで流すな、ということかもしれませんが。

まとめ

まだ本番運用では怖いです。
やはり網羅的にテストを行ってからバージョンアップしたほうが良さそうです。

# 個人的にはOracleSQLServerが安定しているし、実行速度も速いのでそちらを使いたい・・・高くて予算取れないけど。


[PR] 日本でまともに使えるオープンソースCRMが出ています。
f:id:junmt:20151117120041p:plain
CRM構築はオープンソースのF-RevoCRM -エフレボシーアールエム-