はじめに 実戦で踏んだ罠まとめ
Amazon Aurora MySQL v2(MySQL 5.7互換)の標準サポートは2024年10月末で終了しており、現在は RDS Extended Support(延長サポート、有償) で延命している。
本記事では、Aurora MySQL v2 → v3(MySQL 8.0互換)への インプレースアップグレード にフォーカスして、
- 事前準備〜当日作業の具体的なタイムライン
- 切り戻し(ロールバック)計画
- 実戦で踏みやすい罠とその回避策
をまとめます。
将来の v3 → v4 移行でも武器に出来るように参考にして頂けると幸いです。
本記事は「インプレース」中心の構成ですが、最後に Blue/Green Deployment との使い分け にも触れます。
1. アップグレードの2大手法
| 項目 | インプレース(In-place) | Blue/Green Deployment |
|---|---|---|
| 概要 | 既存クラスターを直接アップグレード | 同期された Green 環境を作って切り替え |
| ダウンタイム | あり(数分〜数十分) | 最小限(切り替え時に数十秒程度) |
| 切り戻し | スナップショットからの復元が必要 | Green を破棄するだけで容易 |
| 作業難易度 | 低(AWSが自動処理) | 中〜高(レプリ監視・切替制御が必要) |
| コスト | 低 | 一時的に環境2面分 |
選択基準のざっくり目安
- 検証環境・社内向けシステム・深夜停止OKなら インプレース
- 24/365稼働の本番、ダウンタイムを極小化したいなら Blue/Green
2. 事前計画・事前準備(〜1ヶ月前〜数日前)
インプレースの成否は 事前準備で9割決まります。
2-1. インスタンスタイプの確認と変更
Aurora v3 は古い世代のインスタンス(t2, r4 など)が サポート対象外 です。
該当する場合は、事前メンテで t3 / r6g / r7g などへ変更しておきます。
# 現行インスタンスタイプの確認
aws rds describe-db-instances \
--db-instance-identifier your-db-instance \
--query 'DBInstances[].DBInstanceClass'
2-2. 8.0用パラメータグループの新規作成
5.7用のパラメータグループは流用できません。新規作成して、5.7でカスタマイズしていた値を精査しながら移植します。
特に確認すべきパラメータ
-
sql_mode(後述。最重要) -
character_set_server/collation_server -
lower_case_table_names(8.0は初期化時しか変更不可) default_authentication_plugintime_zonemax_connections-
innodb_*系 -
binlog_*系
2-3. 事前互換性チェック(Upgrade Checker)
AWS CLI で --dry-run 相当の事前チェックを走らせ、ログを error.log から取得します。
aws rds modify-db-cluster \
--db-cluster-identifier your-cluster \
--engine-version 8.0.mysql_aurora.3.07.1 \
--allow-major-version-upgrade \
--no-apply-immediately
実際にチェックされた結果は CloudWatch Logs のアップグレードログに出力されるので、エラー・警告は1件残らず潰します。
2-4. クローン機能でリハーサル
Aurora の Clone はストレージコピーが発生しないため、本番と同じデータで瞬時に検証環境を作れます。
aws rds restore-db-cluster-to-point-in-time \
--source-db-cluster-identifier your-cluster \
--db-cluster-identifier your-cluster-clone \
--restore-type copy-on-write \
--use-latest-restorable-time
ここで 必ず実測すべきこと
- アップグレード完了までの所要時間(→ 当日のメンテ枠の基準)
- アプリからの参照・更新クエリの動作
- スロークエリ・実行計画の劣化有無
- バッチ処理の正常終了
3. 当日作業タイムライン(メンテ枠2時間想定)
| 時刻 | フェーズ | 作業内容 | ポイント |
|---|---|---|---|
| 01:00 | アプリ停止 | アプリ停止 / メンテ画面切替 | DBへの書き込みを完全ゼロに |
| 01:15 | 接続確認 |
SHOW PROCESSLIST; でセッション確認 |
残存セッションを切断 |
| 01:20 | 安全確保 | 手動スナップショット取得 | 切り戻しの命綱。完了まで待機 |
| 01:40 | UG実行 | コンソール or CLI でバージョン変更 | パラメータグループも8.0用へ |
| 01:40〜02:10 | 待機 | 自動処理を監視 | リハーサル時間が目安 |
| 02:10 | 起動確認 | 「Available」状態 / error.log 確認 |
異常ログがないか精査 |
| 02:20 | 疎通確認 | 主要クエリ・主要画面の動作検証 | 事前作成のチェックリストを使う |
| 02:40 | サービス再開 | メンテ画面解除 | 段階的にトラフィックを戻す |
| 03:00 | 経過観察 | CPU / メモリ / スロークエリ監視 | 直後の負荷スパイクに注意 |
切り戻し(ロールバック)計画
インプレースには「元に戻すボタン」がありません。失敗時は以下の手順:
- 作業前スナップショットから新クラスター(5.7)を復元
- Route 53 / アプリ設定でエンドポイントを切替
- アプリ起動・暫定復旧
Go/No-Go判断基準を必ず事前に決める
「02:30 までにアップグレードが完了しなければ、切り戻し処理を開始する」
スナップショット復元は数十分〜数時間かかります。デッドラインを設定しないと、判断が遅れて朝を迎える事故が起きます。
4. 実戦で踏みやすい罠まとめ
事前チェックをすり抜けて当日に牙を剥いてくる地雷たちです。
罠1:新・予約語の衝突
MySQL 8.0 ではウィンドウ関数導入に伴い予約語が増えています。
特に危険な単語:
rankgroupswindowsystemrole-
lead/lag
-- 5.7では動くが、8.0では構文エラー
SELECT rank FROM user_score;
-- 8.0でも動く(バッククォートでエスケープ)
SELECT `rank` FROM user_score;
回避策: ソースコード全体と DB スキーマを grep で洗い出し、該当箇所をエスケープ or 改名。
罠2:sql_mode の厳密化
特に ONLY_FULL_GROUP_BY が牙を剥きます。
-- 5.7(デフォルト)では動くが、8.0では一発アウト
SELECT user_id, name, COUNT(*)
FROM orders
GROUP BY user_id;
-- → name が GROUP BY にも集計関数にもない!
回避策: クエリ修正が王道。間に合わない場合はパラメータグループから ONLY_FULL_GROUP_BY を一時的に外す運用回避。
罠3:デフォルト Collation 変更による JOIN 激重化
8.0 のデフォルト照合順序が utf8mb4_general_ci → utf8mb4_0900_ai_ci に変更。
-- 異なる Collation の JOIN はインデックスが効かずフルスキャン
SELECT *
FROM table_a a
JOIN table_b b ON a.code = b.code
-- a.code が utf8mb4_general_ci, b.code が utf8mb4_0900_ai_ci だとアウト
症状: アップグレード直後から CPU が 100% に張り付く。
回避策
- パラメータグループで
collation_serverを 5.7 時代に合わせる - アプリ側の接続文字列で明示的に文字コードを指定
- 既存テーブル定義の
COLLATEを統一
罠4:クエリオプティマイザの実行計画変化
コストモデルが一新されているため、5.7 では速かったクエリが 8.0 で遅くなることがあります。
確認すべきクエリパターン:
- 複雑な JOIN(特に3テーブル以上)
- サブクエリ(特に相関サブクエリ)
-
ORDER BY+LIMIT -
GROUP BYを含む大量データ集計 - インデックスヒント依存の SQL
回避策: クローン環境のロードテストでスロークエリログを必ず比較。最悪 FORCE INDEX で明示。
罠5:認証プラグインの変更
8.0 のデフォルト認証が mysql_native_password → caching_sha2_password に変更。
影響を受けやすい環境:
- 古い JDBC / Connector/J
- PHP の古い
mysqlnd - Python
PyMySQLの古いバージョン - Node.js
mysql(mysql2ではない方) - 接続プール / RDS Proxy
回避策:
- パラメータグループで
default_authentication_plugin = mysql_native_passwordに固定 - またはアプリ側ドライバを最新化
罠6:コメント欄の不正バイトでアップグレード自体がクラッシュ
地味だが本当に多い罠。過去に古いツールで登録されたテーブル・カラムの COMMENT に、UTF-8 として不正なバイト(Shift_JIS の残骸など)が含まれていると、8.0 のデータディクショナリ移行処理で内部エラーになります。
-- 不正なコメントを探す
SELECT table_schema, table_name, table_comment
FROM information_schema.tables
WHERE table_comment REGEXP '[^[:print:][:space:]]';
SELECT table_schema, table_name, column_name, column_comment
FROM information_schema.columns
WHERE column_comment REGEXP '[^[:print:][:space:]]';
回避策: 事前チェックログで Invalid や文字コード関連エラーを徹底的に確認。怪しいコメントは事前にクリーンアップ。
罠7:lower_case_table_names の変更不可問題
8.0 からは クラスター初期化時にしか設定できません。
5.7 のパラメータグループの値を引き継ごうとして不整合になり、アップグレードが拒否されるケースがあります。
回避策: 8.0 用パラメータグループは「現行と同じ値」を明示的に設定。値が異なる場合は 新規クラスター作成 + データ移行 が必要。
罠8:Aurora v3 はメモリを多く食う
内部構造の変更により、何もしなくても v2 比で数 GB 多くメモリを消費します。
症状: db.t3.medium や db.r5.large で限界運用していた環境で、アップグレード直後に OOM Killer で DB が落ちる。
回避策: アップグレードと同時に 1 サイズ上のインスタンスへスケールアップを強く推奨。
罠9:ストアド・ビュー・トリガー・イベントの破損
アプリ SQL の検証だけでは見落とすポイント。
-- 確認用クエリ
SHOW PROCEDURE STATUS WHERE Db = 'your_db';
SHOW FUNCTION STATUS WHERE Db = 'your_db';
SHOW TRIGGERS FROM your_db;
SHOW EVENTS FROM your_db;
SHOW FULL TABLES WHERE Table_type = 'VIEW';
回避策: クローン環境ですべての DB オブジェクトを一度実行してみる。INVALID 状態や実行時エラーがないか確認。
罠10:バイナリログ・レプリケーション関連
binlog のフォーマットや GTID 関連の挙動が変わっており、外部システムへのレプリやデータ連携基盤(DMS, Kafka Connect など)が止まることがあります。
回避策: binlog を消費している下流システムをすべて棚卸しし、互換性を確認。
罠11:パスワード有効期限
default_password_lifetime のデフォルト値挙動が変わっており、運用しているうちに突然アプリ用ユーザーのパスワードが期限切れになるケースがあります。
-- パスワード無期限化(運用上必要なら)
ALTER USER 'app_user'@'%' PASSWORD EXPIRE NEVER;
5. チェックリスト
## 事前準備
- [ ] インスタンスタイプが v3 サポート対象か確認
- [ ] 8.0用パラメータグループ作成
- [ ] sql_mode の差分精査(ONLY_FULL_GROUP_BY)
- [ ] character_set / collation の整合確認
- [ ] lower_case_table_names の値確認
- [ ] default_authentication_plugin の方針決定
- [ ] 事前互換性チェック実行 + ログ精査
- [ ] 予約語 grep(rank, groups, window, system, role)
- [ ] スキーマ COMMENT の不正バイト確認
- [ ] ストアド・View・Trigger・Event 棚卸し
- [ ] アプリ側 DBドライバのバージョン確認
- [ ] RDS Proxy / 接続プール経由の疎通確認
- [ ] binlog 下流システムの互換性確認
- [ ] クローン環境でアップグレードリハーサル
- [ ] 所要時間の実測
- [ ] スロークエリ比較・EXPLAIN 比較
- [ ] バッチ処理の通し検証
- [ ] 切り戻し手順書の作成
- [ ] Go/No-Go判断時刻の合意
## 当日作業
- [ ] アプリ停止 / メンテ画面表示
- [ ] 接続セッション 0 確認
- [ ] 手動スナップショット取得(完了確認)
- [ ] アップグレード実行
- [ ] error.log 監視
- [ ] Available 状態確認
- [ ] 主要クエリ動作確認
- [ ] 主要画面の動作確認
- [ ] メンテ画面解除
- [ ] CPU / メモリ / スロークエリ監視(最低1時間)
## 切り戻し(必要時)
- [ ] スナップショットから 5.7 クラスター復元開始
- [ ] DNS / 接続先切替
- [ ] アプリ起動
- [ ] 関係者へ報告
6. まとめ
Aurora MySQL のメジャーアップグレードは、「エンジンを上げるだけ」ではありません。
- SQL 互換性
- パラメータ
- 認証方式
- 実行計画
- 文字コード / Collation
- アプリ接続ドライバ
- メモリ使用量
- DB オブジェクト
- 下流システム連携
これらが まとめて変わる のが本質的な難しさです。
延長サポートのコストを考えると早期移行のメリットは大きいですが、焦って一発本番アップグレードを敢行するのは絶対NG。クローン環境でのリハーサルを最低2回は実施し、想定外を想定内に変える地道な作業が、結局は最短ルートです。
「仕組みで解決する」という観点で言えば、社内に Aurora アップグレード手順書テンプレートを残し、次回以降は誰でも再現できる状態にしておくことも大切です。チェックリストとリハーサル手順をパッケージ化しておくと、将来の v3 → v4 移行でも武器になります。