MySQL5.7から8.0にアップグレードする際の手順や詰まったこと
はじめに
明けましておめでとうございます!
弊社ではDBが複数ありますが、そのうちの一つのアップグレードを行ったので、その移行手順や詰まったところをまとめてみました!
移行手順
今回既存のバージョンと、変更しようとしているバージョンです。
エンジンバージョン | |
---|---|
元のバージョン | Aurora(MySQL5.7)2.11.2 |
アップグレードするバージョン | Aurora MySQL 3.08.0(compatible with MySQL 8.0.39) |
DBをアップグレードにあたり、以下のようなやり方が候補に上がりました
データを引き継ぐ方法
- Blue Green
- ダウンタイムが発生するが、GUIでボタンポチポチ押しながらアップグレード
- DMS
- 設定が必要だが、DBの移行ギリギリまでデータ同期可能
- クローン
- クローンした時点でのスナップショットになるので、データの差分が出るがシンプル
DBを差し替える方法
- Route53
- アプリケーション側に事前にレコードを仕込んでおくことで、ダウンタイムをかなり減らせる
- クラスターのリネーム
- 元のクラスターからクローンをする
- 元のクラスターをMySQL8.0にアップグレード
- エンドポイントは変わらない
- 万が一元のバージョンに戻したい場合、元のクラスターを削除し、クローンしたクラスターを元のクラスターの名前にリネームすることで、元のクラスターのエンドポイントを参照できる
- ただし、ダウンタイムが発生する
色々と移行手段が挙がりましたが、今回アップグレードするDBの書き込みが少なかったのと、ダウンタイムを発生させずに移行したかったので、クラスターのクローンと、Route53で切り替えるようにしました。
以下イメージ図です。
クラスターをクローンし、インスタンスを作成
クローンしたクラスターをアップグレード
Route53の向き先をアップグレードしたクラスターに変える
DB移行の全体の流れは、以下の通りです。
- Route53にレコードを作成し、アプリケーション側の環境変数を差し替え
- クラスターをクローンし、インスタンスを作成
- テストデータの作成
- クラスターに対してアップグレードをかける
- Route53で作成したレコードの値に、MySQL8.0のインスタンスのエンドポイントを入れる
- テスト実施
Route53にレコードを作成し、アプリケーション側の環境変数を差し替え
ホストゾーンに新しく、レコードを追加します。
アプリケーション側でDBを参照する際に、MySQL5.7のインスタンスのエンドポイントを直で参照している箇所を、作成したRoute53のレコードを経由するように置き換えていきます。
意図としては、万が一アップグレード後にバグや、速度低下があった場合に、Route53のレコードの値を変えるだけで瞬時に戻せるためです。
クラスターをクローンし、インスタンスを作成
対象のクラスターを選択し、クローンを作成します。
作成時に設定をポチポチしていきます
- データーベース名
- ログのエクスポートにチェック
- スナップショットにタグをコピーにチェック
- 削除保護の有効化にチェック
- マイナーバージョン自動アップグレードの有効化にチェックが外れてること
- スペースマーケットでは、自動アップグレードしない運用にしています。
- メンテナンス期間の設定
など...
クラスターとライターインスタンスができた後、アクション>リーダーの追加からリーダーインスタンスを作成してきます。
テストデータの作成
クローンしたクラスターのデータですが、これはクローンした時点でのスナップショットになります。
ここで、クローンしたクラスターをアプリケーション側に反映する前にスペースマーケット予約や、スペースのお気に入りなどをします。
これは今後の作業で8.0に切り替えた際に、予約を埋めた箇所がカレンダー上で埋まっていなかったり、お気に入りしたスペースがお気に入り状態から外れたりなど、巻き戻りが発生します。
(スペースマーケットでは複数のDBがあるため、画面によっては巻き戻ったり、巻き戻ってなかったりしています。)
巻き戻りが発生するということは、8.0に切り替えられたということなので、クラスターをクローンした段階で、テスト用のデータをこの段階で作成しておきます。
クラスターに対してアップグレードをかける
リーダーインスタンス作成後、変更をクリックし、アップグレグレードをかけていきます。
上記に記載した通り、Aurora MySQL 3.08.0(compatible with MySQL 8.0.39)を選択してアップグレードをかけます。
インデックスの再構築
ところが、アップグレードに失敗します。
ライターインスタンスを選択し、ログと設定から、upgrade-precheck.logを確認すると、以下のようなエラーが出ていました。
{
"id": "auroraUpgradeCheckForFtsSpaceIdZero",
"title": "Check for fulltext index with space id as zero",
"status": "OK",
"description": "The auxiliary tables of FTS indexes on the table are created in system table-space. Due to this DDL queries
executed on MySQL8.0 shall cause database unavailability. To avoid that, drop and recreate all the FTS indexes on the table
or rebuild the table using ALTER TABLE query before the upgrade.",
"detectedProblems": [
{
"level": "Error",
"dbObject": "hoge",
"description": " The auxiliary tables of FTS indexes on the table 'hoge' are created in system
table-space due to https://bugs.mysql.com/bug.php?id=72132. In MySQL8.0, DDL queries executed on this table shall cause database
unavailability. To avoid that, drop and recreate all the FTS indexes on the table or rebuild the table using ALTER TABLE
query before the upgrade."
}
]
}
AWSのドキュメントを見てみると、以下のように記載があります。
該当のテーブル(ここではhoge)ではFULLTEXTインデックスを使用していたのですが、FULLTEXTインデックスを削除しても、内部的に、FTS_DOC_IDカラムや、FTS_DOC_ID_INDEXが削除されずに残ることがあるようです。
テーブルを一度DropしてDBを作り直さないといけないのかなと思っていた矢先、こちらの記事を見つけました。
ALTER TABLE hoge ENGINE = InnoDB
InnoDBの再構築するだけで良さそうです。
再度アップグレードをかけると成功しました。
クラスター・インスタンスの設定値がアップグレード後に引き継がれない
アップグレード完了後にクローン時に設定したものがいくつか漏れていました。
-
クラスター
- 削除保護のチェックが外れてる
-
インスタンス
- パフォーマンスインサイトのチェックが外れてる
- パラメータグループの同期ができてない
クラスター・インスタンスを編集・更新をかけ修正しました。
Route53で作成したレコードの値に、MySQL8.0のインスタンスのエンドポイントを入れる
最初の作成したRoute53の値をクローンし、アップグレードしたインスタンスのエンドポイントに差し替え、terraform applyします。
テスト実施
今回アップグレードしたDBを参照してる箇所に不具合がないかどうかを確認します。
また、上記で記述した通り、データの巻き戻りが発生してるので、同期バッチも走らせ、元の状態の戻ってることを確認します。
感想
フロントエンドとして入社しましたが、これだけインフラを触る機会は中々ないと思うので、とてもありがたいなと思いました。
弊社ではDBが複数あるため、今後のDB移行の施策をやっていくことで更に知識を深めていけたらなと思っています。
最後に宣伝です!
スペースマーケットでは、一緒にサービスを成長させていく仲間を探しています。
とりあえずどんなことをしているのか聞いてみたいという方も大歓迎です!
ご興味ありましたら是非ご覧ください!

スペースを簡単に貸し借りできるサービス「スペースマーケット」のエンジニアによる公式ブログです。 弊社採用技術スタックはこちら -> whatweuse.dev/company/spacemarket
Discussion