MySQL 5.7から8.0へ:安全なアップグレード手順と回避すべき「落とし穴」

MySQL tutorial - IT technology blog
MySQL tutorial - IT technology blog

チェックリスト:5分でわかるMySQLアップグレード

実務での数十件のプロジェクト経験から導き出した、ステージングサーバーですぐに適用できる「クイックな手順」は以下の5ステップです:

  1. 互換性チェック:MySQL Shellをインストールし、util.checkForServerUpgrade()を実行します。8.0の起動直後にデータベースがエラーで停止するのを防ぐため、このステップは決して飛ばさないでください。
  2. 実用的なバックアップ:運に頼ってはいけません。mysqldump --all-databases --routines --events > full_backup.sqlを使用して、最も安全な復元手段を確保しておきましょう。
  3. クリーンシャットダウン:innodb_fast_shutdown = 0を設定してから5.7サーバーを停止し、Buffer Pool内のすべてのデータがディスクに書き込まれたことを確認します。
  4. バイナリの置換:aptまたはyum経由でMySQL 8.0パッケージをインストールします。
  5. ログの監視:MySQL 8.0は自動的にデータ辞書(data dictionary)をアップグレードします。tail -f /var/log/mysql/error.logコマンドで状況を監視しながら待つだけです。

なぜ今すぐMySQL 5.7から移行すべきなのか?

MySQL 5.7は2023年10月に正式に公式サポート終了(EOL)を迎えました。使い続けることは、セキュリティパッチが提供されない脆弱性にシステムをさらすことを意味します。

しかし、本当の理由はパフォーマンスにあります。MySQL 8.0はJSON処理が非常に高速で、CTE(共通テーブル式)のサポートにより複雑なクエリを簡潔に記述できます。私が関わったあるECプロジェクトでは、5.7では複雑なサブクエリを書いていた売上統計処理が、Window関数を活用することで30%も高速化されました。

システム停止を招く恐れのある3つの「致命的な」変更点

アップグレードは単に更新ボタンを押すだけではありません。アプリケーションが即座に動作不能(ハングアップ)になる可能性がある、3つの大きなアーキテクチャの変更点があります。

1. 新しいパスワード暗号化方式

問題点:MySQL 8.0ではデフォルトの認証プラグインがcaching_sha2_passwordに変更されました。古いPHP(7.4未満)や初期のNode.jsを使用している場合、“Authentication method unknown”エラーが発生します。

解決策:コードの修正が間に合わない場合は、my.cnfファイルでMySQL 8.0を旧方式に戻す設定を行います:

[mysqld]
default-authentication-plugin=mysql_native_password

または、特定のユーザーに対して手動で修正します:

ALTER USER 'user_app'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';

2. 予約語の競合 (Reserved Keywords)

問題点:MySQL 8.0の予約語リストには、新たにGROUPSRANKROW_NUMBERなどが追加されました。テーブルにrankという名前の列があり、バッククォート( ` )で囲んでいない場合、クエリは即座に構文エラーを返します。

痛恨の経験:設定列にsystemという名前を付けていたために、CMSシステムが完全にダウンした事例を見たことがあります。8.0に上げた途端、システム予約語との重複でそのモジュール全体が停止しました。手遅れになる前にMySQL Shellでスキャンしてください。

# MySQL Shellでのクイックスキャンコマンド
mysqlsh --user root --execute "util.checkForServerUpgrade()"

3. クエリキャッシュの廃止

現実:MySQL 8.0ではクエリキャッシュが完全に削除されました。非力なサーバーの負荷をこのキャッシュ機能に頼っていた場合、アップグレードした翌日からCPU使用率が20%から80%に跳ね上がることになるでしょう。

解決策:すでに存在しない機能なので、有効化しようとしないでください。インデックスの最適化に注力するか、RedisやMemcachedを使用してキャッシュ層を外部に出してください。

安全なインプレース・アップグレードの手順

これは、リスクを最小限に抑えるためにUbuntuやCentOSサーバーで私がよく使用する方法です。

ステップ1:アップグレード前の確認

破損しているテーブルがないか、またMySQL 5.5時代の古いデータ型が残っていないかを確認してください。以下の全体チェックコマンドを実行します:

mysqlcheck -u root -p --all-databases --check-upgrade

ステップ2:安全なシャットダウンの設定

サービスを停止する前に、メモリ上に残っているすべてのデータをディスクにフラッシュするよう強制します:

SET GLOBAL innodb_fast_shutdown = 0;

その後、サービスを停止します:systemctl stop mysql

ステップ3:インストールと設定

Ubuntuでは、インストールと設定を実行するだけです。インストール中にSHA2パスワードメカニズムについて尋ねられます。アプリケーションが古い場合は、接続エラーを避けるためにRetain MySQL 5.7 Compatibilityを選択してください。

照合順序(Collation)の不一致への対処(旧テーブル vs 新テーブル)

MySQL 8.0はデフォルトでutf8mb4_0900_ai_ciを使用します。既存のデータがutf8_general_ciである場合、新旧テーブル間でJOINを行うとCollation mismatchエラーが発生することがあります。

usersテーブルが1000万行を超えている場合、テーブル全体の照合順序を変更するのは長時間のテーブルロックを伴うため現実的ではありません。私の経験上のアドバイスは、既存のテーブルには古い照合順序をそのまま維持し、新しい機能や今後作成するテーブルにのみ新標準を適用することです。

トラブルを避けるためのヒント

  • 常にクローン環境を使用する:本番環境を操作する前に、データベースをテストサーバーにクローンし、そこでアップグレードプロセス全体を試行してください。
  • RAMの制御:MySQL 8.0は、Performance Schemaだけで約200MB〜500MBのRAMを追加で消費します。サーバーのRAMが1GB〜2GBしかない場合は、OOM(Out of Memory)キラーを避けるためにこの機能をオフにしてください。
  • sql_modeの再確認:8.0ではONLY_FULL_GROUP_BYがデフォルトで有効なため、標準SQLに準拠していない古いPHPコードのGROUP BYクエリが即座にエラーになります。

8.0へのアップグレードは、遅かれ早かれ必要になる作業です。互換性チェックの手順さえ慎重に行えば、発生しうるトラブルの90%は事前に回避できます。

Share: