文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

DBViewerのmetadata lockの罠:その2

DBViewerネタです〜


f:id:treeapps:20180418131549p:plain

d.hatena.ne.jp

MySQLのmetadata lockですが、前回はロック解除ためにサービスを再起動していました。

今回はサービスの再起動ではなく、プロセスをシェルスクリプトで自動的にkillする事で対応してみます。

metadata lockされている時に以下のシェルスクリプトを実行すると、

プロセスを1個kill→metadata lockチェック→プロセスを1個kill→以下ループ

を繰り返し、metadata lockが解除された時点で終了します。(metadata lockしているユーザはshow processlistでは判別できないので、1プロセスづつkillしています)

#!/bin/sh

schema=$1
usage() {
    echo "Usage: `basename $0` <schema>"
    exit 1
}
test -z $schema && usage

MYSQL_CON="mysql -uroot"
MYSQL_CON_INFORMATION_SCHEMA="$MYSQL_CON -Dinformation_schema"
WHERE_CLAUSE="(host like '%local%' or host like '192.168.11.%' or host like '127.0.0.1%') and db = '$schema'"

getLockCount() {
    echo $($MYSQL_CON_INFORMATION_SCHEMA -Ne "select count(*) from processlist where $WHERE_CLAUSE and state = 'Waiting for table metadata lock'")
}

lockCount=`getLockCount`
if [ $lockCount = "0" ]; then
    echo "現在ロックしているユーザはいません。"
    exit 0
fi

# metadata lock状態でないプロセス一覧(stateがmetadata lockと表示されていないプロセスのどれかが犯人)
processes=$($MYSQL_CON_INFORMATION_SCHEMA -Ne "select concat_ws(',',id, host) from processlist where $WHERE_CLAUSE and state != 'Waiting for table metadata lock'")
# 1プロセスづつkill
for proc in ${processes[@]}; do
    id="`echo $proc | awk -F , '{ print $1 }'`"
    host="`echo $proc | awk -F , '{ print $2 }'`"

    $MYSQL_CON -e "kill $id;"
    echo "スキーマ名=$schema、プロセスid=$id、ホスト名=$host、をkillしました。"
    lockCount=`getLockCount`
    echo "ロック数=$lockCount"
    if [ $lockCount = "0" ]; then
        echo "現在ロックしているユーザはいません。"
        break
    fi
done