オンプレMySQLをAurora MySQL Version 3へ移行する時の用心ポイント10か条

この記事はアイスタイル [Advent Calendar 2022](http://qiita.com "アイスタイル Advent Calendar 2022") 22日目の記事です。

みなさんこんにちは、こんばんはアイスタイルでDBA・インフラをやっている[@iwasakik](https://qiita.com/iwasakik)です。
最近超ハイテクなPhase DJというDJ機材をゲットして嬉しい気持ちでいっぱいです。DJもリモートの時代が来てます。

今年のアイスタイルはクラウド化の波がすごい来ているのでMySQLのクラウド化にまつわる話をしたいと思います。
これまでにもMySQLに関する記事をいくつか書いているので、よかったら見てください！

https://techblog.istyle.co.jp/archives/6530

https://techblog.istyle.co.jp/archives/9097

# 目次
<dl>
  <dt>この記事を書くに至った経緯について</dt>
  <dt>オンプレMySQLをAurora MySQL Version 3へ移行する時の用心ポイント10か条</dt>
<table>
  <thead>
    <tr>
      <th>第1条</th> <th>Auroraインスタンス作成後に変更できないパラメータに気を付けよう！</th>
    </tr>
    <tr>
      <th>第2条</th> <th>SQLモードの設定に気を付けよう！</th>
    </tr>
    <tr>
      <th>第3条</th> <th>RDS Proxyのご利用は計画的に</th>
    </tr>
    <tr>
      <th>第4条</th> <th>ログ出力設定は明示的に設定しないと出力されないものもあるので気を付けよう！</th>
    </tr>
    <tr>
      <th>第5条</th> <th>CloudWatchでAuroraの監視アラート設定する際は対象スコープに気を付けよう！</th>
    </tr>
    <tr>
      <th>第6条</th> <th>タグ付けを忘れない</th>
    </tr>
    <tr>
      <th>第7条</th> <th>サーバレスの利用はコストに気を付けよう！</th>
    </tr>
    <tr>
      <th>第8条</th> <th>DBユーザーはmysqldumpリストアではAuroraへ移行されない。<br>この機会にDBユーザーを見直して移行しよう！</th>
    </tr>
    <tr>
      <th>第9条</th> <th>監査ログへの出力条件を吟味しよう！</th>
    </tr>
    <tr>
      <th>第10条</th> <th>大量のDB移行を実施する時はIaC化しよう！</th>
    </tr>
  </thead>
</table>
<dt>まとめ</dt>
</dl>

# この記事を書くに至った経緯について
2022年12月現在、アイスタイルでは大規模なクラウド移行プロジェクトに取り組んでいます。
アイスタイルで利用しているDBには多数のオンプレミスのMySQLサーバーが存在しており、100台以上のオンプレMySQLサーバーをクラウド化する必要があります。

特別な事情が無い限り、クラウド化においてはオンプレMySQLサーバーは全てAmazon Aurora MySQL Version 3へ移行する予定です。
RDS MySQLよりAurora MySQLの方が可用性・運用コスト的にクラウドのメリットをより享受できるためアイスタイルではDBのクラウド移行先としてAmazon Auroraの利用を推奨しています。
また、このタイミングでMySQL8.0互換の最新のバージョンであるAurora Version 3に移行する事でEOL（End Of Life：Extended Support 期限）が迫っている既存の古いMySQLたちを
一気にアップグレードできるという意図もあります（念入りに検証は必要ですが…）。

絶賛クラウド化実施中でまだ道半ばですが、これまで数十台のオンプレMySQLをAurora化してきた中でつまづいたり頭を悩ませたことが42個ぐらいありまして、
その中から厳選してこれからオンプレMySQLのクラウド移行に臨むみなさまにも気を付けてほしいこと10個を用心ポイント10箇条として共有させていただきます
（引き続きクラウド化を進める自分への戒めでもありますw）。
MySQLのクラウド移行に関係ない方々にも少しでも参考になる部分があればいいなぁと思っています。

# オンプレMySQLをAurora MySQL Version 3へ移行する時の用心ポイント10か条
## 第1条　Auroraインスタンス作成後に変更できないパラメータに気を付けよう！
Aurora MySQLにはMySQL関連のパラメータをパラメータグループという形で管理しています。オンプレMySQLでは主にmy.cnfというファイルで管理していたパラメータたちです。
環境構築時に暫定で設定しておいて、後で変更すればいいやと思っていてもAuroraインスタンス作成後には2度と変更できないパラメータがある事をご存じでしょうか。
 **lower_case_table_names**
というパラメータがまさにそれにあたります。
MySQLのデータベース名やテーブル名を大文字小文字で区別するかどうかのパラメータでして、Aurora MySQL Version 3ではデフォルトの設定が0、 **つまり大文字と小文字が区別される** という設定になっています。
このパラメータを1で設定したいのに誤って0でインスタンスを作成した後したことがあったのですが、何をどう頑張っても後から設定変更できませんでした。。

このlower_case_table_namesパラメータを変更するには **インスタンスの再作成が必須となります！気をつけましょう！**

## 第2条　SQLモードの設定に気を付けよう！
MySQLにはSQLモードというパラメータの設定値により、SQL構文やデータの妥当性チェックが他のデータベースよりも柔軟(自由)に設定できます。
MySQLデータベース移行において最も重要なパラメータの一つであり、アプリケーションの要件によっては値を変更している可能性があるので、この設定値は必ず確認すると思います。

ただ、MySQLとAuroraでデフォルト設定が違ったり、バージョンアップによって廃止されているパラメータもあるので注意しましょう。
例えば、下記のようにAurora Version 2(MySQL5.7互換)とAurora Version 3(MySQL8.0互換)ではデフォルトの設定値が0（なし）に設定されています。
```sql:Aurora Version 2(MySQL5.7互換)
mysql> select @@sql_mode;
+------------+
| @@sql_mode |
+------------+
|            |
+------------+
1 row in set (0.00 sec)
```
```sql:Aurora Version 3(MySQL8.0互換)
mysql> select @@sql_mode;
+------------+
| @@sql_mode |
+------------+
|            |
+------------+
1 row in set (0.00 sec)
```
本家のMySQL8.0のデフォルトのSQLモードは標準SQLに合わせるようSQLモードが設定されているので、それと同じだろうと思ってAurora構築時に設定変更せずにいると痛い目を見る羽目になります。。

↓本家のほう（MySQL8.0）

:::note info
MySQL 8.0 のデフォルトの SQL モードには、次のモードが含まれます: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO および NO_ENGINE_SUBSTITUTION。
:::

参考: [MySQL 8.0 リファレンスマニュアル：5.1.11 サーバー SQL モード](https://dev.mysql.com/doc/refman/8.0/ja/sql-mode.html#:~:text=MySQL%208.0%20%E3%81%AE%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%20SQL%20%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AB%E3%81%AF%E3%80%81%E6%AC%A1%E3%81%AE%E3%83%A2%E3%83%BC%E3%83%89%E3%81%8C%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%BE%E3%81%99%3A%20ONLY_FULL_GROUP_BY%2C%20STRICT_TRANS_TABLES%2C%20NO_ZERO_IN_DATE%2C%20NO_ZERO_DATE%2C%20ERROR_FOR_DIVISION_BY_ZERO%20%E3%81%8A%E3%82%88%E3%81%B3%20NO_ENGINE_SUBSTITUTION%E3%80%82)

その他にも、AuroraのSQLモードの設定には少しクセのある部分があるのですが、なにより大切なのは **データベース環境構築後に意図したSQLモードが設定されているか自らの手で確認することです！**

# 第3条　RDS Proxyのご利用は計画的に
2020年6月にRDS ProxyというサービスがGAとなりました。

https://aws.amazon.com/jp/about-aws/whats-new/2020/06/amazon-rds-proxy-generally-available/

アプリケーションとデータベース間の接続をRDS Proxyを介したものにすることで、下記のようなメリットがあり、当初はかなり魅力的なサービスだと感じました。

* コネクションプーリングによる接続時のパフォーマンス効率の向上
* 障害発生時のフェイルオーバー時間減少による可用性の向上
* IAM認証を設定する事によるセキュリティの向上

導入を進めてみるとただアプリケーションとデータベースの間に配置すれば良いものではなく、使いどころを見定めないと下記のようなデメリットもある事が分かりました。

* 直接データベースへ接続するのと比べてコンポーネントを一つ介した接続になるためレイテンシが多少増加する
* 「ピン留め現象」が発生した場合メリットがなくなる
* 追加のコストがかかる

lambdaなどスケールによって大量の接続要求を行うようなサービスとは相性が良いRDS Proxyですが、単純にEC2とAuroraを1:1で利用するシステムなどでは、本当に利用する価値があるのかを見定めた方が良いと思います。
RDS Proxyを利用する際には、 **そのメリットとデメリットを十分吟味したうえで利用するようにしましょう！**

# 第4条　ログ出力設定は明示的に設定しないと出力されないものもあるので気を付けよう！
Aurora MySQLにはCloudWatchにログを出力する機能が存在します。
ログの種類は下記の4通りあります。
* 監査ログ
* エラーログ
* 全般ログ
* スロークエリ

これらのログはデフォルトで出力されるもの・されないものがあり、監査ログ・全般ログ・スロークエリはパラメータグループでそれぞれ下記の設定をしないと意図したログが出力されません。

<table>
  <thead>
    <tr>
      <th>ログの種類</th> <th>関連パラメータ</th>
    </tr>
  </thead>
  <tr>
    <td> 監査ログ </td> <td>server_audit_logging , server_audit_logs_upload , server_audit_events , server_audit_excl_users(もしくはserver_audit_incl_users)</td>
  </tr>
  <tr>
    <td> 全般ログ </td> <td>general_log</td>
  </tr>
  <tr>
    <td> スロークエリ </td> <td>slow_query_log , long_query_time</td>
  </tr>
</table>


特に、スロークエリなどは出力してるつもりだったのに実は出力されていなくて障害時の調査などの際に困る可能性があるので環境構築時には **どのログをどういった要件で出力するかしっかり意識して設定するようにしましょう！**

# 第5条　CloudWatchでAuroraの監視アラート設定する際は対象スコープに気を付けよう！
データベースの障害の前兆を検知して重大な障害を防ぐためにデータベースの監視を行う事はとても重要です。
AuroraではCloudWatchメトリクスの監視アラートを設定する事でデータベースのCPU負荷や接続数の監視を行う事ができます。

ただ、Auroraに対するCloudWatch監視アラートの設定においては、Auroraクラスター全体やインスタンス単位でメトリクスの監視を行っても不十分な場合があります。

例えば、データベースのCPU高負荷アラートを設定する際に、Aurora **クラスター全体**のCPU利用率のメトリクスが閾値を超えた際にアラームを飛ばすように設定をしている場合では、
ライターインスタンスもしくはリーダーインスタンスのどちらか一種類のみCPU利用率100%になっていてもう片方が0%になっているパターンでは
Auroraクラスター全体でみるとCPU利用率は50%になるので高負荷とは判断されない可能性があります。

では、Auroraインスタンス1台1台に監視アラートの設定をしていけば良いと思われますが、スケールアウト・スケールインが柔軟に実施できるAuroraでは構築当初に存在したインスタンスが
運用しているうちに新たに作成されたインスタンスに入れ替わってしまい、その都度監視アラートの設定をし直さなければならない事象が発生してしまいます。

上記のような事態を解消するためには、 **Aurora の Amazon CloudWatch ディメンション** を利用するのが良いと思われます。
例えば"DBClusterIdentifier, Role"でインスタンスロール (WRITER/READER) ごとにメトリクスを集約し、監視アラームを設定すればライターインスタンスのみが高負荷になった場合や、
スケールアウト・スケールインによってインスタンスが入れ替わってもAuroraの障害監視が継続して実施できるのでおススメです。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/dimensions.html

 **ご自身の運用環境に合わせて効果的な監視アラームの設定をしていきましょう！**

# 第6条　タグ付けを忘れない
AWSリソースのコスト管理などをリソースごとに付与するタグで管理している場合、Auroraクラスターを新規構築したりAuroraインスタンスを入れ替える際などに必ずタグ付けを行うようにしましょう。

後述しますが弊社ではAWSリソースの大半をTerraformというIaCを利用して管理しているので、基本的には新規構築時にタグ付けを忘れることはないのですが、
手動でAuroraクラスターへ新たにインスタンスを追加した場合などにはそのインスタンスにはタグが付いていないので忘れずタグ付けを行うようにしています（でないと弊社の場合タグ警察が出動しますw）。

:::note info
タグ警察とはAWSリソースのタグがちゃんと付与されているかを監視する、アイスタイル内で **タグの秩序を守る**メンバーの事です。
:::

新たにAuroraクラスターを構築した際や、スケールアウトやスケールインでAuroraインスタンスの構成が変わった際などは意図したタグが付与されているかしっかり確認するようにしましょう！

# 第7条　サーバレスの利用はコストに気を付けよう！
Amazon Auroraはコンピューティングノードとストレージノードがそれぞれインスタンスとクラスターボリュームという形で分かれています。
![WS000029.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893161/0cad5f0b-99fb-07a4-4bb0-816e52b458d3.jpeg)
参考: [Amazon Aurora DB クラスター](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.html)

さらにインスタンスはあらかじめサイズ・構成を決めておくプロビジョニング済みのインスタンスと、スケーリング管理が不要なサーバレスのインスタンスが存在します。
後者のサーバレスのインスタンスはAmazon Aurora Serverlessと呼ばれており、2022年12月現在v1とv2の2つのバージョンが利用可能です。
特に2022年4月にGAとなったAmazon Aurora Serverless v2は既存のAuroraインスタンスでできたことはほぼすべて踏襲しつつv1よりも高速なスケールアップ・ダウンや
サーバレスインスタンスとプロビジョンドインスタンスの混在が可能になるなど非常に優秀な機能を持ったサービスとなっています。

とても優秀なAmazon Aurora Serverless v2ですが、1点注意点があります。それは **コスト**です！

Amazon Aurora Serverless v2は可変もしくはスパイキーなワークロードには最適なソリューションですが、同等のスペックで比較するとプロビジョンドインスタンスの約5倍のコストがかかるため、
利用が安定しており一定の割合で負荷がかかり続けるようなワークロードではプロビジョンドインスタンスの利用が適していると考えられます。
さらにプロビジョンドの場合、リザーブド DB インスタンスを購入による料金の割引でさらにコストを抑えることができる可能性があります。
実際に弊社でもコストの面で導入を断念したアプリケーションがいくつかあります。

サーバレスは使いどころによっては非常に強力なソリューションですが、 **本番運用時のワークロードとコストをしっかり見極めたうえで適材適所で利用するようにしましょう！**

# 第8条　DBユーザーはmysqldumpリストアではAuroraへ移行されない。この機会にDBユーザーを見直して移行しよう！
データベース移行の際、データの移行を実施するためにmysqldumpを利用する機会が多いと思います。
弊社ではクラウド化の際に移行元データベースのmysqldumpを取得し、移行先となるAuroraへリストアを実施してレプリケーションを組むことが多いです。

ここでリストア実施時に注意しなければならない事があります。

データベース全体のmysqldumpをAuroraにリストアしようとしてもAuroraに対してはmysqlデータベースをリストアする事はできないのでリストアが失敗します。リストア時には個別のデータベース単位でのmysqldumpのリストアが必要です。
```bash:管理者ユーザー（admin）でデータベース全体をリストアしようとするとこちらのエラーになる
ERROR 1044 (42000) at line 30075: Access denied for user 'admin'@'%' to database 'mysql'
```
すなわち、ユーザー情報が含まれるmysql.userデータベースを他のMySQLからリストアする事ができないので、MySQLユーザーの情報は個別に設定していく必要があります。

DBユーザーの移行が実施されない事で、改めてDBユーザーを作成しなおすという手間が増えてしまうことを当初はネガティブに捉えていたのですが、発想を転換するとこの機会にDBユーザーの棚卸と整理ができるので良いことだなと思いました。
現在、各アプリケーションチームへの確認を行いながら、ユーザーの整理を行いながらオンプレMySQLのクラウド化を進められています。

mysqldumpを利用してオンプレMySQLからAuroraへの移行を実施する場合はこの機会に **DBユーザーの見直しを実施する事をオススメします！**

# 第9条　監査ログへの出力条件を吟味しよう！
第4条でも触れましたが、Auroraではパラメータグループで監査ログの出力設定を行う事ができます。
それぞれ下記が監査ログ関連のパラメータです。

<table>
  <caption>監査ログ関連パラメータ</caption>
  <thead>
    <tr>
      <th>パラメータ</th> <th>意味</th> <th>値</th>
    </tr>
  </thead>
  <tr>
    <td> server_audit_logs_upload </td> <td>CloudWatch Logs に監査ログを発行する</td> <td>1</td>
  </tr>
  <tr>
    <td> server_audit_logging </td> <td>監査を有効または無効にする</td> <td>1</td>
  </tr>
  <tr>
    <td> server_audit_events </td> <td>ログに記録するイベントのコンマ区切りリスト</td> <td>イベントはすべて大文字で指定する必要があり、リスト要素の間に空白を入れないでください

例）CONNECT,QUERY_DDL</td>
  </tr>
  <tr>
    <td> server_audit_excl_users </td> <td>アクティビティをログに記録されないユーザーのユーザー名のコンマ区切りリスト</td> <td>指定するユーザー名Userは、mysql.userテーブルの列の対応する値と一致する必要があります

例）rdsadmin,user_1,user_2</td>
  </tr>
  <tr>
    <td> server_audit_incl_users </td> <td>アクティビティがログに記録されるユーザーのユーザー名のコンマ区切りリスト</td> <td>指定するユーザー名Userは、mysql.userテーブルの列の対応する値と一致する必要があります

例）user_1,user_2</td>
  </tr>
</table>

監査ログの出力は要件によってどのような情報を出力するか変わってくると思いますが、特に条件を絞らずにすべてのユーザーのすべてのイベントを記録するようにしてしまうと、
CloudWatchログのストレージを大幅に消費してしまい無駄なコスト増につながってしまう可能性があります。
弊社では最低限、rdsadminやアプリケーションDBユーザーの監査ログの出力はされないように設定し、必要に応じて設定をカスタマイズしています。

監査ログには誰のどんなイベントを出力するべきか **今一度よく検討したうえで設定を行うようにしましょう！**

# 第10条　大量のDB移行を実施する時はIaC化しよう！
私がクラウド移行を実施する中で最も重要だと感じたポイントの一つがDB周りのインフラ構築・運用時においてコードを用いて運用管理を行う事でした。いわゆるIaC（Infrastructure as Code）の活用です。
弊社ではこの目的を達成するためにTerraformを採用しており、クラウド移行したAuroraは全てTerraformコードで管理しています。

多少学習コストはかかりますが、コード管理を行う事には下記のメリットがあると考えられます。

* 構成変更の履歴をコードで残すことができる
* 手順のロストなどによるブラックボックス化を防ぐことができる
* 繰り返し行う処理をコード化し再利用可能な状態にすることができる
* コード化する事でインフラ・DBA以外のチームへもノウハウの共有がしやすくなる

100台以上のデータベースをクラウド化するにあたり、基本的にいくつかのパラメータやスペック以外は同じ設定で環境構築を行うので、もしこの作業をすべて手作業でAWSのコンソール画面から行う事になっていたらと考えるとゾッとします。
第6条でお伝えしたタグ付けについても、Terraformコード化する事で極力つけ忘れを防止する事ができます。
また、これまでにお伝えした用心ポイントの大半はコード化する事で **作業漏れを無くす事ができます！**

この第10条だけで1記事書けるぐらいお伝えしたい事がたくさんあるのですが、ここでは実体験を通してそのメリットを大いに感じることができたという事が少しでも伝わればと思います。

これからクラウド化を進めたり、現在MySQLのクラウド化を実施しているけど手作業で実施している方にはぜひ **リソースのコード化をオススメします！**

# まとめ
今回 **クラウド移行×MySQL**という観点で記事を書かせていただきましたが、MySQLの環境構築時における基本的な知識やAWS特有の設定方法など、実際に経験した中で重要だと思われるポイントをまとめられたと思います。
第2条、第8条ではどちらかというとMySQLの環境構築時に気を付ける内容、それ以外のポイントはどちらかというとクラウド化、Amazon Auroraへ移行する際の注意点をお伝えしています。

今回ご紹介した用心ポイントは私個人の見解も多く含まれていますが、どの用心ポイントもオンプレMySQLのクラウド化を一歩一歩進める上でつまづき、頭を悩ませた事だったので、
すでに知ってる！という方には共感していただけたら嬉しいですし、これからクラウド化を進める方にとっては今回の記事を見て同じポイントで躓かず、すこしでもお役に立てたら嬉しいです。

記事を書いていて、同じようなミッションに取り組んでいる方々の用心ポイントも知りたいと思ったのでいつかそういったお話を聞く機会があればいいなと願っています。

以上、最後までお読みいただきありがとうございました。