DBViewerネタです〜
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