-
概要 最近、Aurora2(MySQL5.7)だったクラスターをAurora3(MySQL8.0)にアップグレードしたところ、特定のクエリだけが失敗するという事象があった。 ClowdWatchLogsに出力していたerrorログには /tmp/xxx is full! と出力されていた。 Aurora2(MySQL5.7)の時代にはなかったことだったので、Aurora3(MySQL8.0)によるものであることはわかり、それが新しく採用されたTempTableストレージエンジンによるものであることがわかった。 TempTableストレージエンジンとはどういったものか、Aurora3の仕様もあわせて色々わかったので記録をしておこうと思います。 最初に結論 Aurora2からAurora3にアップグレードする際には temptable_max_ram と temptable_max_mmap の値を必ず確認して、必要に応じて調整したほうが良い。 TempTableストレージエンジンとは 詳細な説明は下記を参照してもらうとして、ざっくり説明すると内部一時テーブルを使うようなクエリを実行した場合に、MySQL5.7のときにつかっていたInnoDBテーブルではなくメモリを利用したストレージエンジンとなり、5.7のときよりも効率的にクエリを処理することができるようになったストレージエンジンのことを指す。 https://dev.mysql.com/doc/refman/8.0/ja/internal-temporary-tables.html TempTableストレージエンジンでは temptable_max_ram を上限としてオンメモリで処理されて、それを超えると、temptable_max_mmap を上限として、mmap()システムコールにより、ローカルストレージにファイルを作成して、仮想メモリにマッピングを行う。 ページサイズ単位(Linuxではデフォルト4KiB)でメモリ上にデータがロードされるので、InnoDBテーブルに変換される場合よりも、効率的(可変長)で高速に処理される。 では、temptable_max_mmap を超えたサイズのデータをクエリするような場合はどのような挙動になるか。 MySQL8.0の挙動 Aurora3に関わらず、MySQL8.0の仕様では、temptable_max_mmap を超えると、InnoDBテーブルに書き込むようになる。 つまり、遅くはなるけど処理は継続される。 Aurora3の挙動 Aurora3ではどうなるかというと、ライターとリーダーで挙動が異なる。 ライターはMySQL8のデフォルトの挙動と同じになるが、リーダーの場合は temptable_max_mmap の値を超えると /tmp/xxx is full!とエラーが出力されてクエリが失敗する。 temptable_max_ram と temptable_max_mmap はデフォルト1GiBなので、合計2GiBを超えるようなクエリは失敗して終了してしまう。 原因についてはAWSサポートにも確認してわかっているが、まずAuroraは共有ストレージを採用しており、 そして、リーダーインスタンスは共有ストレージを参照は可能だが、書き込みはできない。 内部一時テーブルを作成するのにあたり、ライターは問題にならないがリーダーインスタンスで、MySQL5.7のときは共有ストレージではなく、ローカルストレージにMyISAMとして書き込みを行う仕様だった。 リーダーインスタンスでは、オンディスク一時テーブルはローカルストレージを使用する MyISAM ストレージエンジンを使用します。これは、読み取り専用インスタンスでは Aurora クラスターボリュームにデータを保存できないためです。 https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.CompareMySQL57.html MySQL8.0.16以降、内部一時テーブルのストレージエンジンを指定していた internal_tmp_disk_storage_engine が廃止されて、デフォルト InnoDB となった。 Auroraでもこの仕様に則り、Aurora2では internal_tmp_disk_storage_engine が適用され、Aurora3では internal_tmp_mem_storage_engineが適用されるようになった。 パラメータグループをみても、Aurora2のときにあった internal_tmp_disk_storage_engine は Aurora3では見当たらず、かわりに internal_tmp_mem_storage_engine のみが存在する。 https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Reference.ParameterGroups.html internal_tmp_mem_storage_engine はメモリを使った内部一時テーブルの処理のみとなり、デフォルトが TempTable で、MEMORY にも変更は可能である。MySQL Created
28 Dec 2023 -
概要 Auroraクラスターの検証をしていて、とある理由で停止しておきたいけど、しばらくは削除したくないというときがある。 Auroraは自動的に停止7日後に自動で起動してきてしまう。 そこで、なんとかできないか色々見てたらEventBridgeと会社の同僚氏から提案されたSSMオートメーションの組み合わせが一番良かったので記録しておきます。 構成 Auroraクラスター EventBridgeルール SSMオートメーション Terraform まず、必要なIAMを作成する。 対象のクラスターに対してのみ、参照と停止の権限を付与する。 resource "aws_iam_role" "stop_db_clusters" { name = "automation-stop-db-clusters" assume_role_policy = data.aws_iam_policy_document.stop_db_clusters.json inline_policy { name = "automation-stop-db-clusters" policy = jsonencode( { "Version" : "2012-10-17", "Statement" : [ { "Sid" : "rds", "Effect" : "Allow", "Action" : [ "rds:StopDBCluster", "rds:DescribeDBClusters" ], "Resource" : [ "arn:aws:rds:ap-northeast-1:123456789:cluster:example-db1", ] }, { "Sid" : "ssm", "Effect" : "Allow", "Action" : "ssm:*", "Resource" : "*" } ] } ) } } data "Created
2 Oct 2023 -
概要 最近、Auroraのインスタンスサイズを下げようと検討しているインスタンスがあったので、購入済みのリザーブドインスタンスから試算することになった。 そこで、Aurora、およびRDSのリザーブドインスタンスの知識として、知らなかったことがいくつかあったのでその記録。 結論 RDSには柔軟性の考え方がある(Auroraも該当する) インスタンスファミリーが同じ場合に適用される 柔軟性は小さいインスタンスクラスのインスタンスから適用される RDSには柔軟性の考え方がある。 RDSのリザーブドインスタンスを購入する際の基本知識として、柔軟性の考え方がある。 https://aws.amazon.com/jp/about-aws/whats-new/2017/10/amazon-rds-reserved-instances-offer-instance-size-flexibility/ 新規および既存の RDS RI すべてにおいて、同じデータベースエンジンを使用する DB インスタンスファミリーの任意のサイズで使用量に応じた割引が自動的に適用されます。RI ディスカウントの割引はまた、同じデータベースエンジンおよび DB インスタンスファミリーのシングル AZ とマルチ AZ の両方の設定で使用量に応じて適用されます。 これがどういうことか説明する前に、RDSのインスタンスにはクラスごとに正規化係数というのが定められている。 2017年10月以降、RDSのインスタンスサイズが異なる場合でも、購入しているリザーブドインスタンスが適用されるというもの。 公式サイトの例でみると、もしt2.mediumのリザーブドインスタンスを購入している場合に、t2.mediumではなくて、t2.smallが2台でもリザーブドインスタンスが適用されるということである。 この場合、シングルAZだったとして、t2.mediumの正規化係数は2であり、t2.smallの正規化係数は1であり、それが2台なので購入済みのリザーブドインスタンスの正規化係数と同じになるので、追加でオンデマンド費用は発生しないこととなる。 これは、リザーブドインスタンスを最初に1つ購入したものの、あとからインスタンスサイズを下げて2台に冗長化するといった場合でもリザーブドインスタンスが無駄にならないようになっている。 インスタンスファミリーが同じ場合に適用される これは同じインスタンスファミリーにしか正規化係数は合算されないので、t2.smallのリザーブドインスタンスがあっても、t4g.smallには適用されず、そのままオンデマンド費用となるということ。 インスタンスファミリーに関しては、リザーブドインスタンス購入後は諦めて同じものを使い続けたほうが良さそうだ。 柔軟性は小さいインスタンスクラスのインスタンスから適用される 最後のこれが中々理解が難しかった。 例えば、下記場合にどうなるか。 例: 購入済みのリザーブドインスタンスは以下となる(いずれもシングルAZで同一インスタンスファミリー)。 2xlarge x 1 正規化係数は16である。 次の場合に、下記インスタンスを所有するとリザーブドインスタンスの適用はどのようになるか。 2xlarge x 1 xlarge x 1 まず、2xlargeのリザーブドインスタンス16から、xlargeの1台分8が引かれて残り8となる。 次に、2xlargeのリザーブドインスタンス8から、2xlargeの1台分16のうち8が引かれて0となる。 残りの2xlargeの正規化係数8については 2xlargeのオンデマンド費用 として請求される。xlargeの1台のオンデマンド費用ではないところがミソである。 まとめ 試算しているときに請求書をみていたら、なぜか追加購入していないはずの一番でかいインスタンスサイズのオンデマンド費用が発生していて疑問に思って調べてわかった。 特に最後のところは、AWSサポートにも確認して、認識に違いが無いことがわかった。 期初にリザーブドインスタンスをぴったりで購入したあとに、追加で低いインスタンスサイズのRDSを購入したからそれだけオンデマンドになるだろうと思ったら、そうじゃないので注意が必要。 また、柔軟性を知らないと、リザーブドインスタンスの期限が切れるギリギリまで待たないと、インスタンスサイズが下げられない!と勘違いをしてしまうかもだが、正規化係数によっては損をしない可能性がある。 これからインスタンスサイズを下げたいな〜と思ってたり、RDSの請求書に追加購入していないのにオンデマンド費用が発生していたら、このあたりを確認すると良さそうです。 <p style='padding: 5px;'>Created
16 Aug 2023 -
ことの始まり ある日、社内の簡易ツールをリリースしたいという相談を受けました。 社内ツールだし、料金は抑えたいけど、MySQLを使いたいという要望だったので、構築のモチベーションの1つにAuroraServerlessが使えないかを検証をすることにしました。 RDSの料金はt3.microだとして、超ざっくり月額2000円程度です。 RDSの料金 AuroraServerlessの料金はACUという単位で、1ACUが**$0.06/hなので、まるまる動かすと4800円**程度で、RDSよりもAuroraである分高くなります。 AuroraServerlessの料金 なので、営業時間の間だけしか使わないようなツールであれば、8時間だと1600円程度で安くなります。 ということで、AuroraServerlessを検証するべく作業を始めたところ、全然関係ないところで色々余計な作業が発生してしまいました。 問題発生 検証環境で、AuroraでServerlessのインスタンスを作成するべくAWSコンソールでポチポチしていたのですが、ふと疑問が1つ。 VPCでサブネットを選択しようとすると、なぜか選択出来ません。 新規作成となってしまい、仕方なくそのまま先に進めようとしたところ、下記エラーが表示されて作成出来ず。 Aurora Serverless doesn't support DB subnet groups with subnets in the same Availability Zone. Choose a DB subnet group with subnets in different Availability Zones. 1つのAZで複数サブネットを配置した場合のエラーのようでした。 元々検証環境では、1つのAZに1つのサブネットで、マルチAZにしていました。 しかしながら、複数サブネットにしている認識がなかったので確認したところ、たしかに複数サブネットが配置されているようでした。 どうやら、どこかのタイミングで、だれかがポチポチ追加してしまった模様で、RDSは全てのサブネットを追加するボタンがあるので設定変更あたりで間違って追加しちゃったのかなぁという感じでした。 改めて現状を整理すると、 – 全てのサブネットを追加してしまっているのがどうやら過去のどこかのタイミングで発生している。 – 弊社ではDB用のサブネットを1AZに1サブネット作成している。 ここで勘の良い方はすぐに気がつくと思いますが、本来配置すべきではないサブネットにDBインスタンスがいくつか配置されていることがわかりました。 検証環境なので、外部からのアクセスは出来ないようになってはいますが、本番環境とは異なるネットワーク設定に加えて、パブリックサブネットに配置されてしまっているDBもあり適切ではないので即座に対応をすることにしました。 上記のAuroraServerless作成時のエラーを解消するには下記作業が必要であることがわかりました。 1.対象のサブネットグループから不要なサブネットを削除する 2.不要なサブネットに配置されているインスタンスを正しいサブネットに配置しなおす 対処の実施 ということで、まず不要なサブネットを1つづつ削除していき、エラーになったサブネットを洗い出しました。 その後、管理しているDBインスタンスのIPアドレスをdigで調べて、どのサブネットに配置されているかを確認。 スナップショットと、念の為mysqldumpを実施して、一回不要なサブネットに配置されてしまっていたDBインスタンスを全て削除しました。 新たな問題 意図したサブネットに配置されたインスタンス以外を全て削除した後、不要なサブネットを1つずつ削除していき、最後の1つを削除しようとしたところ何故か Some of the subnets to be deleted are currently in use のエラーが。。Created
14 Feb 2020 -
手順 RDSの場合、mysql cliコマンドではrootでもgeneral_logを有効にできないので、AWSコンソールから実施する。 パラメータグループ 対象のインスタンスのグループ パラメータでgeneral_logの値を 1(有効), 0 (無効) にする general_logは大量に吐かれるので本番ではやらない。検証環境でも一時的に有効したら無効化しておく。 general_logを削除する TRUNCATE TABLE general_log ではrootでも権限により削除できない。 削除のためのストアドプロシージャが用意されているのでストアドから実行する。 なお、一回実行したら general_log_backup へ退避されるので、完全に削除したい場合は rds_rotate_general_logというストアドを2回実行する。 mysql> select count(*) from general_log; +----------+ | count(*) | +----------+ | 301603 | +----------+ 1 row in set (2.13 sec) mysql> call rds_rotate_general_log ; Query OK, 0 rows affected (0.02 sec) mysql> select count(*) from general_log; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.Created
13 Jul 2018