AWS RDS 必須メンテナンスを延期する裏技

# はじめに

本来、必須メンテナンスはデータベースの安全な使用のため、必ずするべき内容なので、先延ばしするべきではありません。
とはいえ、色々な事情があって、そうも言ってられない場合もあるかと思います。

例えば、次のメンテナンスウィンドウが来週月曜日のAM4時だが、その時間に対応できるスタッフがいないのと、
強制アップデートが走るとサイトパフォーマンスが悪化することがわかっている場合など。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130352/f4e47ce3-04b0-4c7a-864f-d5ce0a24e64f.png)

以下のやり方で、最大で7日、メンテナンスを延期することが出来ます。

# メンテナンス日時の延期手順

1. RDS > データベース > {DB識別子} > 変更 をクリック
2. 追加設定 > DB インスタンスのメンテナンス期間
    * 開始日: 現在日付と同じ曜日を選択
        * 現在日付が`4/23 (水)`ならば、`水曜日`を選択
    * 開始時間: 現在時間よりも【前】のUTC時間を選択
        * 現在時間が`4/23 11:00 JST`ならば、`10:00 JST`→`01:00 UTC`を選択
        * 現在時間よりも後の時間を選ぶと、メンテナンス日時がむしろ前倒しになり、強制アップデートがすぐ走ったりするので注意
        * 強制アップデートは 開始時間すぐに始まることが多いです。4:00 JST開始ならば、4:02に開始したりします(1敗)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130352/bcd3c45f-80bc-4804-a362-2e66ed86b834.png)
3. 「続行」をクリック
4. 「すぐに適用」を選択し、「DBインスタンスを変更」をクリック
    * この変更だけならインスタンスの再起動は発生しませんので、「すぐに適用」で大丈夫です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130352/daa9375d-7ca5-4885-9586-382bdca60a5b.png)
5. 「メンテナンスとバックアップ」タブをクリックし、メンテナンスウィンドウの時間が7日後になったことを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130352/0ab07933-2f61-429c-aded-41284a454396.png)
6. さらに延期したい場合、次のメンテナンスウィンドウの時間が来るよりも前に、1～5の手順を行うことで再度、延期可能

もちろん、これはその場しのぎの対応なので、アップデートするべきものは早めにアップデートしてください。

# 強制アップデートが走っちゃった！どうすれば元に戻せるのか？

だいたい、強制アップデートに気づくのはアップデート後、数時間経過してからのことだと思います。
そのため、DBを復元した後、現行のDBからデータを取得して、置き換える必要があります。

幸いにも、強制アップデートの場合、自動的にアップデート直前のタイミングのスナップショットが作成されます。
04:02 JST に強制アップデートが走った場合、04:02に自動でスナップショットが用意されています。

まずはインスタンスをスナップショットから復元した後、dumpデータを流し込むことで復元が可能です。

【注意】エンドポイントURLが変わってしまうので、アプリケーション側の修正が必要になります

## スナップショット復元の手順

1. RDS > 左サイドバー「スナップショット」 > 「システム」タブ をクリック
2. 「スナップショットの作成時刻」を降順に並び替える
3. `rds:preupgrade-{db識別子}-{以前のDBバージョン}-to-{新しいDBバージョン}-{タイムスタンプ}` 形式のスナップショットがあるはずなので探す
    * 具体例: `rds:preupgrade-my-rds-database-name-10-4-34-to-10-11-10-1745175734140`
4. 対象のスナップショットをチェックし、アクション > 「スナップショットを復元」をクリック
5. DBインスタンス識別子に現在の識別子とは違うものを設定する
    * オススメは現在の識別子に年月日を付けるやり方です
    * 例: `my-rds-database-name-250423`
6. インスタンスの設定 > 現在のDBと同じインスタンスサイズを選択する
    * 現在のDBのインスタンスサイズは継承されていないので注意
7. ストレージタイプやストレージ割り当ても、現在のDBと同じであることを確認する
8. 接続 > VPCやDBサブネットグループの設定が、現在のDBと同じであることを確認する
9. 接続 > 既存のVPCセキュリティグループに、現在のDBと同じものを割り当てる
    * 現在のDBのセキュリティグループ設定は継承されていないので注意
10. 接続 > アベイラビリティゾーンに、現在のDBと同じものを割り当てる
    * 現在の(ry
11. 追加設定 > DBパラメータグループに、現在のDBと同じものを割り当てる
12. 追加設定 > ログのエクスポート > スロークエリログをオンにする
13. 「DBインスタンスを復元」をクリック
    * 確認画面なしですぐにインスタンスの作成が発生(=課金が発生)するので注意

## RDSインスタンス復元後の設定調整

1. DBの作成完了後、RDS > {DB識別子} > 変更をクリック
2. ストレージ > 追加のストレージ設定 > 「ストレージの自動スケーリングを有効にする」のチェックが外れている場合はチェックする
3. モニタリング > Performance Insights を有効化をチェックする
4. モニタリング > その他のモニタリング設定 > 拡張モニタリングの有効化をチェックする
5. 追加設定 > DB インスタンスのメンテナンス期間 > 開始日および開始時間を上に書いたやり方で調整する
6. 続行をクリック > 今すぐ適用 をクリック

## DBバックアップの方法

後は、普通にDB作成するのと同じ手順です。
このあたりはphpMyAdminを使うなり、皆さんの普段やり慣れたやり方で行ってください

```bash
# 1. DB移行元と移行先の設定
# NOTE: 事前に移行先のRDSインスタンスを用意すること
DB_RDS_ID="my-rds-database-name"
DB_RDS_HOST_ID="xx6dexhyixx3"
DB_MIGRATE_FROM_SUFFIX="250421"
DB_MIGRATE_TO_SUFFIX="250427"
DB_REGION="ap-northeast-1"
# 2. 環境変数の設定
DB_HOST_MIGRATE_FROM="${DB_RDS_ID}-${DB_MIGRATE_FROM_SUFFIX}.${DB_RDS_HOST_ID}.${DB_REGION}.rds.amazonaws.com"
DB_HOST_MIGRATE_TO="${DB_RDS_ID}-${DB_MIGRATE_TO_SUFFIX}.${DB_RDS_HOST_ID}.${DB_REGION}.rds.amazonaws.com"
DB_NAME="my_database_name"
DB_USERNAME="my_user_name"
BACKUP_FILE="${DB_NAME}.$(date +%Y%m%d%H%M).sql.gz"

# 3. DB移行元から バックアップを圧縮状態(.sql.gz)で取る
mysqldump -h $DB_HOST_MIGRATE_FROM -p -u $DB_USERNAME $DB_NAME | gzip > $BACKUP_FILE
```

## DBインポート方法

```bash
# 4. DB移行先に ログインしてDBを再作成する
mysql -u $DB_USERNAME -p -h $DB_HOST_MIGRATE_TO

DROP DATABASE my_database_name; CREATE DATABASE my_database_name;

# 5. DB移行先に インポートを実行する
zcat $BACKUP_FILE | mysql -u $DB_HOST_MIGRATE_TO -p -h $DB_HOST $DB_NAME

# 6. テスト環境で DB接続先を一時的に変更して動作確認する
# 7. 問題なさそうなら、本番環境のDB接続先を変更する
# 8. テスト環境のDB接続先を元に戻して作業完了
```