概要
なんかよくわからないけど DB の負荷が高くなったどー
という監視アラートが出たとき、あなたはどうしますか?
そういうときに何が原因で負荷が高くなっているかサクッと追いたいですね。
CPU の状態や、スワップの状態、コネクション数から調べることもできますが、これだけでは何が原因で重くなったのかはっきりしないことは多いです。
対象読者
- aws が何なのか知っている人、運用している人 (aws は食べ物ではない)
- RDS で DB 管理していること
- スロークエリログを cloudwatch もしくは DB に保存できる環境であること
準備
DB 側
数秒でサクッと原因を特定できるようにするためには、事前に準備が必要です
まずは RDS のパラメータグループで以下の設定を変更してください (デフォルトのパラメータグループでは変更できないようです)
- slow_query_log: 1
- long_query_time: 0.1 ~ (単位 秒)
- log_output: FILE (TABLE でもよいですが、その場合の方法は今回は割愛)
次に、RDS 自体の設定で [Modify] を設定し、[Slow query log] にチェックをいれます
そうすることで RDS の Configuration に Slow query という cloudwatch へのリンクができます。
リンク先を開くと、キャプチャの ① が log-group-name で ② が log-stream-name です。メモしておきましょう。
集計側 (local など)
セットアップ
mac の場合 homebrew 導入済みの前提で記載しますと、以下のように percona-toolkit を導入します
$ brew install percona-toolkit
jq コマンドも導入しておきます
$ brew install jq
mac の場合は、以下のように aws-cli を導入します
$ brew install awscli
$ aws configure // aws の設定を行う
スクリプト配置
ということで、 slow-query-summary.sh
というスクリプトで中身を以下のようにします
pt-query-digest のオプションを指定すれば、explain も出したり、余計なクエリをフィルタしたりできますが、ここでは割愛します
LOG_GROUP
には先程メモした log-group-name
を、 LOG_STREAM
には先程メモした log-stream-name
をいれます
mac - FreeBSD系
#!/bin/bash -u
LOG_GROUP=hogehoge
LOG_STREAM=fugafuga
SCRIPT_NAME=`basename $0`
if [ $# -ne 2 ]; then
echo "指定された引数は$#個です。" 1>&2
echo "実行するには2個の引数が必要です。" 1>&2
echo "Usage: $SCRIPT_NAME "\""2019-12-01 12:00:00"\"" "\""2019-12-01 13:00:00"\" 1>&2
exit 1
fi
start="$1"
end="$2"
echo start datetime iso-8601..
echo $(TZ=JST-9 date -jf "%Y-%m-%d %H:%M:%S" "$start" +%s);
echo end datetime iso-8601..
echo $(TZ=JST-9 date -jf "%Y-%m-%d %H:%M:%S" "$end" +%s);
starttime=$(expr `TZ=JST-9 date -jf "%Y-%m-%d %H:%M:%S" "$start" +%s` \* 1000)
endtime=$(expr `TZ=JST-9 date -jf "%Y-%m-%d %H:%M:%S" "$end" +%s` \* 1000)
aws --profile prod logs get-log-events \
--log-group-name ${LOG_GROUP} \
--log-stream-name ${LOG_STREAM} \
--start-time ${starttime} \
--end-time ${endtime} \
--query 'events[].message' \
|jq -r '.[]' \
| pt-query-digest --limit 10000
gnu 系
#!/bin/bash -u
LOG_GROUP=hogehoge
LOG_STREAM=fugafuga
SCRIPT_NAME=`basename $0`
if [ $# -ne 2 ]; then
echo "指定された引数は$#個です。" 1>&2
echo "実行するには2個の引数が必要です。" 1>&2
echo "Usage: $SCRIPT_NAME "\""2019-12-01 12:00:00"\"" "\""2019-12-01 13:00:00"\" 1>&2
exit 1
fi
start="$1"
end="$2"
echo start datetime iso-8601..
echo $(TZ=JST-9 date --iso-8601="seconds" --date "$start");
echo end datetime iso-8601..
echo $(TZ=JST-9 date --iso-8601="seconds" --date "$end");
starttime=$(expr `TZ=JST-9 date --date "$start" +%s` \* 1000)
endtime=$(expr `TZ=JST-9 date --date "$end" +%s` \* 1000)
aws --profile prod logs get-log-events \
--log-group-name ${LOG_GROUP} \
--log-stream-name ${LOG_STREAM} \
--start-time ${starttime} \
--end-time ${endtime} \
--query 'events[].message' \
|jq -r '.[]' \
| pt-query-digest --limit 10000
最後に実行権限をつけます
$ chmod +x ./slow-query-summary.sh
重くなったなというときに、以下のようにスクリプトを実行すれば、簡単にスロークエリログのサマリが表示されるようになります。
./slow-query-summary.sh "2019-12-01 12:00:00" "2019-12-01 13:00:00"
※キャプチャはサマリの部分だけですが、実際のスロークエリログもでてきます