Aurora Serverlessの自動スケールが失敗するときは ForceApplyCapacityChange を有効にしよう!

2020.03.22

Amazon Aurora Serverless はワークロードに応じてキャパシティが自動的にスケールします。

いざ評価してみると、スケールアップが繰り返し失敗し、いつまでもキャパシティが増えないことがあります。

そのようなときは ForceApplyCapacityChange オプションを有効にしましょう。

説明

Aurora Serverless の FAQ でスケールしない理由が説明されています。

Q: Aurora Serverless DB クラスターが自動的にスケールしないのはなぜですか?

Aurora Serverless では、スケーリングオペレーションが開始されると、データベースのスケーリングを安全に行える時点となるスケーリングポイントを見つけようとします。Aurora Serverless では、進行中の長期のクエリやトランザクションがある場合や、一時的なテーブルやテーブルロックを使用している場合、スケーリングポイントを特定できないことがあります。

スケーリングポイントを検出できないままタイムアウトすると、デフォルトではスケーリングオペレーションはキャンセルされます。

キャパシティーの強制変更オプションを有効にすることで、必要に応じてスケーリングポイントの検出を妨げる接続を切断し、キャパシティーが変更されるようになります。

やってみた

この動作を実際に確認してみます。

評価方法

Aurora Serverless クラスターを作成し、キャパシティを1〜4の範囲で変化するようにします。

適当にテーブルを作成し、ダミーデータを投入します。

キャパシティが低い状態で、処理に時間のかかるクエリーを投げ、ForceApplyCapacityChange オプションの有効・無効による挙動の違いを確認します。

強制オプション無効状態

強制オプションがデフォルトの無効状態のまま、キャパシティが2の状態で数十分かかる重いクエリーを投げます。

$ mysql -h db.XXX.rds.amazonaws.com -u admin -p test \
  -e "select count(1) from data a join data b join data c join data d join data e"
Enter password:s
...

Log & Events タブを確認すると、スケーリングオペレーション開始イベントを確認できます。

Time System Notes
Sat, 21 Mar 2020 13:53:50 GMT Scaling DB cluster from 2 capacity units to 4 capacity units for this reason: Autoscaling.

クエリーが完了しないため、5分程度でタイムアウトが発生し、スケーリングオペレーションがキャンセルされます。

Time System Notes
Sat, 21 Mar 2020 13:58:53 GMT The DB cluster failed to scale from 2 capacity units to 4 capacity units for this reason: A scaling point wasn’t found.
Sat, 21 Mar 2020 13:53:50 GMT Scaling DB cluster from 2 capacity units to 4 capacity units for this reason: Autoscaling.

約1.5分後、重いクエリーは継続中で、スケールアップが必要なため、再びスケーリングオペレーションが開始されます。

Time System Notes
Sat, 21 Mar 2020 14:00:30 GMT Scaling DB cluster from 2 capacity units to 4 capacity units for this reason: Autoscaling.
Sat, 21 Mar 2020 13:58:53 GMT The DB cluster failed to scale from 2 capacity units to 4 capacity units for this reason: A scaling point wasn’t found.
Sat, 21 Mar 2020 13:53:50 GMT Scaling DB cluster from 2 capacity units to 4 capacity units for this reason: Autoscaling.

クエリーが完了しない限り、以降はスケーリング→タイムアウト→キャンセルが繰り返されます

Time System Notes
Sat, 21 Mar 2020 14:12:34 GMT The DB cluster failed to scale from 2 capacity units to 4 capacity units for this reason: A scaling point wasn’t found.
Sat, 21 Mar 2020 14:07:17 GMT Scaling DB cluster from 2 capacity units to 4 capacity units for this reason: Autoscaling.
Sat, 21 Mar 2020 14:05:34 GMT The DB cluster failed to scale from 2 capacity units to 4 capacity units for this reason: A scaling point wasn’t found.
Sat, 21 Mar 2020 14:00:30 GMT Scaling DB cluster from 2 capacity units to 4 capacity units for this reason: Autoscaling.
Sat, 21 Mar 2020 13:58:53 GMT The DB cluster failed to scale from 2 capacity units to 4 capacity units for this reason: A scaling point wasn’t found.
Sat, 21 Mar 2020 13:53:50 GMT Scaling DB cluster from 2 capacity units to 4 capacity units for this reason: Autoscaling.

強制オプション有効状態

この状態で、DB クラスターの強制オプションを有効にします。

スケーリングポイントの検出にタイムアウトすると、クエリーが切断されます。

$ mysql -h db.XXX.rds.amazonaws.com -u admin -p test \
  -e "select count(1) from data a join data b join data c join data d join data e"
Enter password:
...
ERROR 1080 (08S01) at line 1: /rdsdbbin/oscar/bin/mysqld: Forcing close of thread 9  user: 'admin'

RDS のイベントログを確認すると、スケーリングオペレーション開始から約5.5分後(=タイムアウト後)にキャパシティが変更(has scaled)されていました。

Time System Notes
Sat, 21 Mar 2020 14:19:47 GMT The DB cluster has scaled from 2 capacity units to 4 capacity units.
Sat, 21 Mar 2020 14:14:18 GMT Scaling DB cluster from 2 capacity units to 4 capacity units for this reason: Autoscaling.
Sat, 21 Mar 2020 14:XX:XX GMT ForceApplyCapacityChange オプション有効化
Sat, 21 Mar 2020 14:12:34 GMT The DB cluster failed to scale from 2 capacity units to 4 capacity units for this reason: A scaling point wasn’t found.

Capacity に 対応するメトリクス Serverless Database Capacity を CloudWatch から確認します。

ForceApplyCapacityChange を使わずにキャパシティを変更する方法

スケーリングポイントを特定できないのは、進行中の長期のクエリやトランザクションがある場合や、一時的なテーブルやテーブルロックを使用している場合です。

SHOW FULL PROCESSLIST\G で問題のあるプロセスを特定し、CALL mysql.rds_kill(99)/CALL mysql.rds_kill_query(99); で kill してスケーリングポイントを作ることも回避可能です。

個人的には、せっかく Aurora Serverless を使用するのなら、強制変更オプションを有効にして手離れよく運用したほうが良いのではないかと思います。

参考