俺の報告

RoomClipを運営するエンジニアの日報(多分)です。

日報 #24 - MySQL最終防衛システム

いやぁしかし、、、
「つまめるようになったなぁ」と思っていた腹回りがあっという間にこんなボテ腹になるんだから、 寄る年波というのは本当に凶悪ですね。

マックのポテトLサイズを貪り食うような無邪気さは完全に消え失せ、
酒もやらず、ヤニもくわず、カロリーと糖質を気にした飯を舐めるなんて、
終末感と閉塞感のお手本のような景色なわけです。

まぁ、とはいえ、

自由奔放に食い散らかして、バカスカ煙草を吸っていた時代が煌めいていたかと言われると、別に大して変わらないというのが正直なところです。

俺の腹は確かに残念な感じだし、
糖尿病も肺がんも肝硬変も怖いけど、
世界を鷲掴みにするために、今日も今日とて必死に頑張るわけであります。

さて日報ですが、 今日は枕が長かったので、完結なところで。

MYSQLのスロークエリは大変危険なシロモノです。
分かりきったご法度中のご法度なわけで、本来起こりうるはずがありません。
しかし、だからといって
いつ、なんどき、なんかの遠因となんかの遠因が重ね合わさって、
極稀に「重たいクエリ」が走る可能性を否定してはイカンわけであります。
そしてそれほどの異常事態の場合、数秒で終わってくれるスローではなく、
サービス全体を揺るがす爆弾クエリの可能性もあるわけです。
(何度も言いますが、あっちゃならないのですけどね)

ということで、最後の最後の絶対防衛ラインというものを作っておきたくなるのは人の世の常。
「5秒以上かかっているクエリは、発注元がマッカーサーであってもkillしろ!」
これが絶対防衛ライン、世界を守る最終防衛システム(SaGa2参照)なわけです。
ということで、作ってみましょう。

#! /bin/sh

MYSQL_USER=hoge
MYSQL_PASS=hoge_pass
MYSQL_HOST=hoge.rds.amazonaws.com
TIME_OUT_SEC=5

MYSQL_MAX_TIME_PROCESS=`mysqladmin processlist -h $MYSQL_HOST -u $MYSQL_USER -p$MYSQL_PASS | awk 'BEGIN { FS="|"; } /Query/ {print $2,":",$7,":",$9}' | sort -t':' -nrk  2 | head -n 1`

QUERY_ID=`echo $MYSQL_MAX_TIME_PROCESS | cut -d':' -f1`
QUERY_TIME=`echo $MYSQL_MAX_TIME_PROCESS | cut -d":" -f2`
QUERY_INFO=`echo $MYSQL_MAX_TIME_PROCESS | cut -d":"  -f3`

if [ $QUERY_TIME -ge $TIME_OUT_SEC ]; then
mysqladmin kill $QUERY_ID -h $MYSQL_HOST -u $MYSQL_USER -p$MYSQL_PASS
fi 

肝なのは2つ。

  • processlistを使って、現在走っているクエリリストを取得すること。
    mysqladmin processlistで引っ張ります

  • そしてそのQuery Timeを抽出し、ソートして一番大きい行を抽出すること。
    awkの識別子を|に変更し、各行のQuery Timeの値をsortで並び替えし、headで先頭を取得

こうすることで、TIME_OUT_SEC以上の時間がかかっているクエリはkillされます。 そのタイミングでメールとか放っておけば完璧ですね。

とはいえ、これは最終防衛システムなわけで、
グングニルの槍をもったメカとフレアを覚えた魔導師と、力99の人間男、
ニンフくらいには進化したモンスターがいないと戦っちゃ駄目です。
(SaGa2参照)

以上ですた。
運動しようね。