💽

Amazon Aurora MySQL5.7のサポート期限が迫ってきたのでMySQL8に移行した話

2024/04/18に公開

こんにちは、アルダグラムのSREエンジニアの okenak です

弊社のサービスのDBにAmazon Auroraを利用していますが、MySQL5.7の標準サポートが2024年10月31日までであるため、MySQL8の移行を実施しました。(サポート期限について)

今回は移行に伴い調査したことや対応手順、実際に起きた問題について紹介したいと思います。

Aurora MySQL8のアップグレード内容の調査

MySQL5.7からMySQL8の移行だったので、公式ガイドを見て機能差分の調査を行いました

MySQL :: MySQL 8.0 リファレンスマニュアル :: 2.11 MySQL のアップグレード
Amazon Aurora MySQL DB クラスターのメジャーバージョンのアップグレード - Amazon Aurora

ドキュメントを一通り読んだところ気になったポイントは以下の部分でした

  • GROUP BYの暗黙ソートがされなくなる変更
    • 上記に依存した処理がある場合は挙動が変わるので
  • distinct使用時、selectリストにない項目でORDER BY すると怒られるようになった
    • 使ってる箇所があれば修正が必要
  • パフォーマンス影響がないかどうかの調査
    • オプティマイザの実行に影響が出るようになっている
    • ソートの挙動が変わったのでsort buffer sizeのエラーが出ないか
  • 予約語にrankが追加
    • 弊社サービスのテーブル名やカラム名でrankを使ってる箇所はなかった
  • インスタンスタイプにdb.t3.smallが利用不可
    • 最小単位がdb.t3.mediumになるため開発環境などで使ってるAuroraの料金が上がる
  • sql_modeからNO_AUTO_CREATE_USERの削除
    • 弊社サービスでは指定してる箇所はなかった

Aurora MySQLのどのバージョンを選択するか検討

2023年4月現在は最新の3.0.6.0がリリースされていますが、以下は当時調査時点での内容です
(3.05.0と3.05.1共に現在は廃止されており、3.05.2しか選べないようになってる模様です)

Aurora version MySQL version トピック情報 リリースノート
3.05.1 8.0.32 ・当時のAurora最新版(security fix版)
・機能面やmysqlのバグの状況は3.05.0と同じ
リンク
3.05.0 8.0.32 ・再起動時間が最大65%短縮
UNION ALLの日本語検索のバグがある
ALGORITHM=INSTANTの制限が一部解禁
リンク
3.04.1 8.0.28 長期サポートの対応(LTS) リンク

本番環境の移行プロセス

  1. ローカル環境を先にアップデートして影響範囲の洗い出しと修正を実施
    • Docker環境をMySQL8に移行してローカルで動作確認を行って検知された箇所を修正
    • Rspecのテストコードで検知された箇所の修正
  2. MySQL8アップデート検証環境を構築して網羅的なQAを実施
    • QAチームの協力を元に全体テストを実施して機能デグレがないかどうかチェック
    • MagicPodを使ったE2Eテストを実施して基本動作シナリオで検知された箇所の修正
  3. 本番環境をメンテナンスモードに切り替えアップデートを実施

本番環境の切り替え方式については、Aurora Blue/Green deployment なども検討してみましたが、問題が発生した時の切り戻しが複雑な点や、IaCツールとの相性が悪いことから採用を見送りました。

MySQL8で挙動が変わり修正が必要だった箇所

あまり多くはなかったですが軽微なところで並び順や空文字比較の箇所に影響が出ました

  • 暗黙的なソートが発生している箇所で並び順に影響が出る問題

    • GROUP BY未使用箇所でもORDER BYの最適化の影響か挙動が変わるケースがありました

    • 対応としてはソート順でorder byを明示することで解決しています

              order('companies.id asc').
              order('users_belong_to_companies.role asc').
      +       order('users.id asc')
          end
      
  • 日付型に対して空文字で比較指定をしてる箇所がエラーになる問題

    • MySQL5.7でもWarningだったのですがMySQL8からはエラーが吐かれるようになり発覚

    • 対応としてはフィールドの型が日付型の場合は判定条件を変えるようにしました

      -            return query.concat(
      -              [
      -                "#{table}.#{field} IS NULL",
      -                "#{table}.#{field} = ''",
      -                "#{table}.#{field} #{direction}",
      -                "#{DEFAULT_TABLE}.id #{direction}",
      -              ],
      -            ).join(', ')
      
      +            # MySQL8から日付型の空文字比較でエラーになるためOrderByの条件を変更する
      +            if DATE_FIELDS.include?(field)
      +              return query.concat(
      +                [
      +                  "#{table}.#{field} IS NULL",
      +                  "#{table}.#{field} #{direction}",
      +                  "#{DEFAULT_TABLE}.id #{direction}",
      +                ],
      +              ).join(', ')
      +            else
      +              return query.concat(
      +                [
      +                  "#{table}.#{field} IS NULL",
      +                  "#{table}.#{field} = ''",
      +                  "#{table}.#{field} #{direction}",
      +                  "#{DEFAULT_TABLE}.id #{direction}",
      +                ],
      +              ).join(', ')
      +            end
      

総括

QAメンバーによる高精度の総合テスト、MagicPodを使用したE2Eの自動デグレードチェック、そして開発メンバーが日々努力しているユニットテストの向上のおかげで、大きな障害もなく最小限の工数でMySQL 8へのアップグレードを無事成功させることができました!

今回の成果は、開発チームが一丸となって取り組んだ結果だと考えています。
もし本記事が誰かのお役に立てると幸いです。

もっと、アルダグラムのエンジニア組織を知りたい人は、下記の情報をチェック!

アルダグラム Tech Blog

Discussion