MySQLを本番で運用する場合、
今回は第12回から少し応用をきかせた監視方法を説明したいと思います。第12回で説明した事柄は今回は省略しますので、
mysql
コマンドを利用した監視スクリプト
データベースが問題なく動いているかどうかを確認するためにはMySQLの外側から監視する必要がある、mysql
コマンドを利用したシェルスクリプトとして作ってみます。
#!/bin/bash export MYSQL_PWD="test" if mysql -h127.0.0.1 -P64056 -uyoku0825 -e "quit" > /dev/null 2>&1 ; then echo "Connection succeeded." exit 0 else echo "Connection failed." exit 2 fi
MYSQL_
環境変数にはMySQLへのログイン用パスワードを設定します-p
オプションにパスワードを指定することなくそのパスワードを利用してログインを試行します)。スクリプトの中でやっていることは、mysql
コマンドに-h
オプションで接続先IPアドレスを指定、-P
オプションでポート番号を指定、-u
オプションで監視用のユーザー名を指定して、-e
オプションで"quit"コマンドを送信しています。つまり、
mysqladmin ping
コマンドに比べると、
続いて、
#!/bin/bash export MYSQL_PWD="test" set_timeout="SET SESSION innodb_lock_wait_timeout=1; SET SESSION lock_wait_timeout=1" if mysql -h127.0.0.1 -P64056 -uyoku0825 -e "quit" > /dev/null 2>&1 ; then if mysql -h127.0.0.1 -P64056 -uyoku0825 --init-command="$set_timeout" -e "SELECT * FROM d1.t1 WHERE rand() < 0.01 ORDER BY _rowid DESC LIMIT 100 FOR UPDATE" > /dev/null 2>&1 ; then echo "Connection and data fetching succeeded." exit 0 else echo "Connection succeeded but data fetching failed." exit 1 fi else echo "Connection failed." exit 2 fi
innodb_
オプションとlock_
オプションを1
InnoDBのSELECT
は本来ロックフリーですが、FOR UPDATE
を明示することで排他ロックを取ることができます。このステートメントの取ったロックはmysql
コマンドの終了時点で開放されます。他の書き込みステートメントと競合してロック待ちのタイムアウトが発生するとmysql
コマンドが0以外の終了コードを返すため、
今度はこれを複数テーブルに対応させてみます。
#!/bin/bash export MYSQL_PWD="test" set_timeout="SET SESSION innodb_lock_wait_timeout=1; SET SESSION lock_wait_timeout=1" if mysql -h127.0.0.1 -P64056 -uyoku0825 -e "quit" > /dev/null 2>&1 ; then mysql -h127.0.0.1 -P64056 -uyoku0825 -sse "SHOW TABLES FROM d1" | while read table ; do if mysql -h127.0.0.1 -P64056 -uyoku0825 --init-command="$set_timeout" -e "SELECT * FROM d1.${table} WHERE rand() < 0.01 ORDER BY _rowid DESC LIMIT 100 FOR UPDATE" > /dev/null 2>&1 ; then echo "Connection and data fetching succeeded on d1.${table}." else echo "Connection succeeded but data fetching failed on d1.${table}" exit 1 fi done exit 0 else echo "Connection failed." exit 2 fi
-ss
オプションSHOW TABLES
ステートメントでテーブルの一覧を取り出してwhile read
でループさせています。SELECT
に成功した場合は続きのテーブルを改めてSELECT
しますが、_rowid
というシノニムを使っているため、
#!/bin/bash export MYSQL_PWD="test" set_timeout="SET SESSION innodb_lock_wait_timeout=1; SET SESSION lock_wait_timeout=1" if mysql -h127.0.0.1 -P64056 -uyoku0825 -e "quit" > /dev/null 2>&1 ; then mysql -h127.0.0.1 -P64056 -uyoku0825 -sse "SHOW TABLES FROM d1" | while read table ; do have_autoinc=$(mysql -h127.0.0.1 -P64056 -uyoku0825 --init-command="$set_timeout" \ -ssEe "SHOW CREATE TABLE d1.${table}" | grep "AUTO_INCREMENT" | wc -l) if [ "$have_autoinc" = "1" ] ; then check_sql="SELECT * FROM d1.${table} WHERE rand() < 0.01 ORDER BY _rowid LIMIT 100 FOR UPDATE" else check_sql="SELECT * FROM d1.${table} WHERE rand() < 0.01 ORDER BY NULL LIMIT 100 FOR UPDATE" fi if mysql -h127.0.0.1 -P64056 -uyoku0825 --init-command="$set_timeout" -e "$check_sql" > /dev/null 2>&1 ; then echo "Connection and data fetching succeeded on d1.${table}." else echo "Connection succeeded but data fetching failed on d1.${table}" exit 1 fi done exit 0 else echo "Connection failed." exit 2 fi
SHOW CREATE TABLE
の出力結果を縦表示-E
オプション)
細かいことを言えば、mysql
コマンドが起動するたびにコネクションを張り直しているため、
また、INSERT
してROLLBACK
する方が確実にロック以外の面も含めて書き込みができるであろうことを保証できます。試しに排他ロックを取ってみる必要もないかも知れません、information_
テーブルで実行中のトランザクションを確認することができますので、
おっと、SHOW SLAVE STATUS
の結果も欠かせません。マスターとの接続は途切れていないか、Seconds_
カラムの値から判断することができます。余裕があればSHOW GLOBAL STATUS LIKE 'Threads_
とSHOW GLOBAL VARIABLES LIKE 'max_
の比較をしてみてもいいでしょう。Threads_
がmax_
の9割近くを占めているなら、
おわりに
監視プラグインは