はじめに
MySQLのメジャーバージョンアップは怖いですよね。データが消えないか、クエリが遅くなっていないか、切り戻しできるか。
レプリケーションを使うと切り替え時のダウンタイムを最小化しながら、安全にバージョンアップできます。今回は『MySQL運用管理 [実践] 入門』第5章を読んで、MySQL 5.7→8.0のアップグレード手順を整理しました。
基本的な考え方
MySQLは一つ上のメジャーバージョンまでのレプリケーションを公式でサポートしています。
MySQL 5.7(ソース)→ MySQL 8.0(レプリカ) ✅ サポート
MySQL 5.6(ソース)→ MySQL 8.0(レプリカ) ❌ 非サポート
これを利用して、新バージョンのMySQLをレプリカとして動かしながら、切り替えのときだけ短いダウンタイムでアップグレードできます。
アップグレードの全体の流れ
1. 構成の確認
2. MySQL 8.0のサーバーを用意
3. オプション値の確認
4. ユーザーアカウントの作成
5. データのコピー
6. レプリケーションの構築
7. 切り替え前の確認
8. 切り替え
1. 構成の確認
MySQL公式のMySQL Shellアップグレードチェッカーユーティリティでアップグレードに影響のある問題点を事前に確認します。
mysqlsh -u root -p -h 127.0.0.1 -P 3306 -e "util.checkForServerUpgrade()"
20以上のチェック項目があります。主なものはこちらです。
- 新しい予約語と衝突するオブジェクト名
- utf8mb3文字セットの使用
- 64文字以上の外部キー制約名
- 削除されたオプション
sql_modeのフラグの使用 - 削除された関数の使用
エラーが返された項目はアップグレード前に手動での修正が必要です。
2. MySQL 8.0のサーバーを用意
移行先のMySQL 8.0のサーバーをソースとレプリカの2台用意します。
アプリケーション
↓
MySQL 5.7ソース MySQL 8.0ソース
↓ ↓
MySQL 5.7レプリカ MySQL 8.0レプリカ
3. オプション値の確認
MySQL 8.0でデフォルト値が変わったオプションを確認して、移行元に合わせます。
| オプション名 | MySQL 5.7デフォルト | MySQL 8.0デフォルト |
|---|---|---|
character_set_server |
latin1 | utf8mb4 |
collation_server |
latin1_swedish_ci | utf8mb4_0900_ai_ci |
default_authentication_plugin |
mysql_native_password | caching_sha2_password |
explicit_defaults_for_timestamp |
OFF | ON |
event_scheduler |
OFF | ON |
特に character_set_server と collation_server は移行元に合わせておかないと、インポート時に意図しない文字セットでテーブルが作成されることがあります。
# MySQL 8.0側のmy.cnf
[mysqld]
character_set_server = utf8mb4
collation-server = utf8mb4_general_ci # 移行元に合わせる
4. ユーザーアカウントの作成
ユーザーアカウントは mysql スキーマのテーブル構造がバージョンによって異なるため、移行元からコピーせず手動で移行先に追加します。Percona Toolkitの pt-show-grants を使うと簡単に移行できます。
pt-show-grants -h 127.0.0.1 -u root -P 3306 --ask-pass
5. データのコピー
mysqldumpでユーザースキーマのみをエクスポートして移行先へインポートします。
# ポジションレプリケーションの場合
mysqldump -h 127.0.0.1 -P 3306 -u root -p \
--single-transaction \
--default-character-set=utf8mb4 \
--source-data=2 \
--routines --triggers --events --hex-blob \
--databases db1 db2 > mysql57.source.dump
# インポート
cat mysql57.source.dump | mysql -h 192.168.0.2 -P 3306 -u root -p
インポート時はバイナリログにインポートした更新がすべて書き込まれてしまうため、ディスクサイズを確認しながら進めます。
6. レプリケーションの構築
MySQL 5.7ソースをソース、MySQL 8.0ソースをレプリカとしてレプリケーションを構築します。
-- MySQL 8.0側で実行
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='192.168.0.1',
SOURCE_PORT=3306,
SOURCE_USER='repl_user',
SOURCE_PASSWORD='repl_password',
SOURCE_LOG_FILE='binlog.000004',
SOURCE_LOG_POS=157;
START REPLICA;
レプリケーションの遅延が解消されるまで待ちます。移行元レプリカと移行先インスタンスは不要な書き込みを防ぐために read_only = ON にしておきます。
7. 切り替え前の確認
切り替え前に3点確認します。
データベースオブジェクトの比較
information_schema のテーブルで移行元と移行先のオブジェクトを突き合わせます。
-- information_schemaで確認できる主なテーブル
-- TABLES, COLUMNS, STATISTICS, TRIGGERS, ROUTINES, EVENTS
SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database';
行ベースレプリケーションはオブジェクトがなくてもレプリケーションエラーにならないため、切り替え前に確認が必要です。
データの整合性確認
CHECKSUM TABLE または Percona Toolkitの pt-table-checksum でデータの整合性を確認します。
-- シンプルな確認方法(書き込みロックが発生するためオフラインのレプリカで実行)
CHECKSUM TABLE t0;
pt-table-checksum はオンラインで実施可能です。ソースに実行してレプリケーションを通じてレプリカにも同じクエリを実行させ、それぞれのハッシュ値を比較することで整合性を検証できます。
クエリ性能の確認
バージョンアップで実行計画が変わってクエリが遅くなることがあります。移行元のスロークエリログやパケットキャプチャでクエリを収集し、移行先で実行して性能を比較しておきます。
クエリの収集方法:
- スロークエリログ
- 一般クエリログ(General Log)
- パケットキャプチャ(tcpdump + pt-query-digest)
8. 切り替え
切り替えの手順は5ステップです。
① 移行元を読み取り専用にする
② 移行元と移行先のデータの状態を確認する
③ 移行先のレプリケーションを停止する
④ Webアプリケーションの接続先を変更する
⑤ 移行先の書き込みを許可する
① 移行元を読み取り専用にする
-- 移行元で実行
SET GLOBAL read_only = ON;
② データの状態を確認する
移行元で SHOW MASTER STATUS を実行して最新のバイナリログポジションを確認します。
-- 移行元で実行
SHOW MASTER STATUS;
-- File: binlog.000006, Position: 175957498
-- 移行先で実行
SHOW REPLICA STATUS\G
-- Relay_Source_Log_File と Exec_Source_Log_Pos が一致していることを確認
③ 移行先のレプリケーションを停止する
-- 移行先で実行
STOP REPLICA;
FLUSH BINARY LOGS; -- 切り替え後の更新が新しいバイナリログから始まるようにする
④ Webアプリケーションの接続先を変更する
アプリケーションの接続先をMySQL 5.7からMySQL 8.0に変更します。
⑤ 移行先の書き込みを許可する
-- 移行先で実行
SET GLOBAL read_only = OFF;
以上でアップグレード完了です。
コラム:バックワードレプリケーション(切り戻し用)
アップグレード後に問題が発生した場合に備えて、MySQL 8.0をソース、MySQL 5.7をレプリカにするバックワードレプリケーションという手法があります。
ただしMySQL公式ではサポートされていません。character_set_serverをutf8mb4に設定している環境ではレプリケーションを構成するとエラーになるなど、いくつかの制限があります。
スポットでの切り戻し対応としての利用を検討する場合は、十分な検証を行い危険性を認識した上で実施してください。
RDSの場合
RDSのメジャーバージョンアップはAWSがこの手順を自動化しています。ただし仕組みを知っておくことで以下の点を理解できます。
- なぜアップグレード前に事前確認(パラメータグループ・文字セットなど)が必要なのか
- なぜアップグレード時に短いダウンタイムが発生するのか(切り替えのタイミング)
- アップグレード後にクエリが遅くなることがあるのはなぜか(実行計画の変化)
まとめ
- レプリケーションを使うとダウンタイムを最小化しながらバージョンアップできる
- 切り替え前に必ずアップグレードチェッカー・データ整合性・クエリ性能の3点を確認する
- デフォルト値が変わったオプション(character_set_server等)は移行元に合わせておく
- 切り替え手順は「移行元を読み取り専用 → データ状態確認 → レプリケーション停止 → 接続先変更 → 書き込み許可」の5ステップ
- バックワードレプリケーションは公式非サポートなため十分な検証が必要