code up

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

MySQLの接続数を取得し続けるスクリプト

MySQLのとあるデータベース(mydb)への接続数を延々と監視し続けるスクリプト。

11接続以上になるとshow processlistの表示結果をコンソールに出力する。

普段はおとなしいのに定期的に接続数が爆発しているらしくたまに次のエラーがログに出ていた。エラー通知は来るんだけど、使っている監視ツールの通知後に確認するといつも穏やかな状態に戻っていて困っていた。

Caused by: org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
        at org.apache.tomcat.dbcp.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:104)
        at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
        ... 59 more
Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
        at org.apache.tomcat.dbcp.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1134)
        at org.apache.tomcat.dbcp.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:96)

いつまで経ってもその瞬間の現場を押さえられないため、本スクリプトをコンソールで垂れ流しておき、現場を押さえるのと、その時どんなSQLが流れているかを確認するために作成。

#!/bin/sh

while :
do
  count=`mysql -e "show processlist;" -u root | grep mydb | grep -v Sleep | wc -l`
  if [ $count -gt 10 ]; then
    now=`date`
    mysql -e "show processlist;" -u root
    echo $now $count
  fi
  sleep 1
done
# シェルの実行結果(標準出力、エラー出力)をファイルにリダイレクトしつつ、コンソールにも出力
$ /tmp/tmp.sh 2>&1 | tee /tmp/tmp.log

1. 検知したら、kill -3 pidでTomcatのスレッドダンプを取って、catalina.outからスレッドダンプを抜き出す。

# ":set nu"で行番号を表示させて行番号を控える
$ vi catalina.out

# 行番号176244から1816行がスレッドダンプだった場合
$ tail -n +176244 catalina.out | head -n 1816 > /tmp/dump.txt

2. その瞬間のCPU利用率を調べる。top, vmstat, mpstatとか。

3. で、接続数が爆発した時は、あるアップデート文が多く時間を要していることが分かり、とあるDAOクラスにてトランザクション処理の実装が悪いことが判明。

続き

それでもやっぱりたまに画面の表示が遅くなることがあった。Javaのsynchronizedな部分もあやしいんだけど、とりあえずデータベース周りで他に問題がないかを調査するため、mpdump, mpfilter, mpreportを拝借してさらに追試。

#!/bin/sh

while :
do
  count=`mysql -e "show processlist;" -u root -h 127.0.0.1 -P 13306 | grep mydb | grep -v Sleep | wc -l`
#  echo $count
  if [ $count -gt 10 ]; then
    now=`date`
    rnd=$RANDOM
    mysql -e "show processlist;" -u root -h 127.0.0.1 -P 13306
    echo $now $count
    ~/trunk/mpdump --host=127.0.0.1 --port=13306 --samples=3000 > ~/mpdump.$rnd.txt
    ~/trunk/mpfilter < ~/mpdump.$rnd.txt | ~/trunk/mpreport | head -30 > ~/result.$rnd.txt
  fi
  sleep 1
done

上のファイルにmpdumpシリーズの処理を追加したスクリプト。接続数が11を超えたらmpdumpを使ってMySQLに対してshow processlistを投げ続け高負荷なSQL文を洗い出してもらう。

サーバー側にPerlのDBIなどは入っておらず、改めてインストールするのも大変(yumとかapt-getもない環境)なので、Windowsのcygwin上にて構築。sshで13306ポートをサーバーのMySQL(3306)にポートフォワードしている状態。

関連記事
タグ:MySQL bash
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。