MySQL 5.7.5の新機能ネタ。
いままでMySQLでgraceful shutdownぽいことをしようとすると、SET GLOBAL max_connections= 1 で接続を制限するくらいしか思いつかなかったけれども(LVSとかでやりくりするのは除く)
* 接続を切断するわけではないので、Connector/Jのコネクションプーリング的なものとかと相性が悪い
* クライアントにはError: 1040 (ER_CON_COUNT_ERROR) "Too many connections" が戻ってしまう
* しかも、Error: 1040は通常運用でも異常系として発生しうるので、区別してハンドルするのはかなり無理ゲー
と、イマイチgraceful shutdownの夢を見切れなかったけれども。
5.7.5で追加されたオフラインモードが多少なりとも夢を見させてくれるかも知れない。
オフラインモードは
* SET GLOBAL offline_mode= 1で有効化
* オフラインモードだと、Super_privを持っていないユーザーは接続できない
* Super_privを持っていないユーザーのセッションは、トランザクションが終了次第コネクションを切断される
という機能。
http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_offline_mode
tpcc_startをかけながら、以下のコマンドでドン。
mysql> SHOW PROCESSLIST; SET GLOBAL offline_mode= 1; SHOW PROCESSLIST;
+----+------+-----------+------+---------+------+----------------+------------------------------------------------------------
------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info
|
+----+------+-----------+------+---------+------+----------------+------------------------------------------------------------
------------------------------------------+
| 7 | root | localhost | NULL | Query | 0 | starting | SHOW PROCESSLIST
|
| 8 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 997 WHERE w_id = 1
|
| 9 | tpcc | localhost | tpcc | Execute | 0 | Writing to net | UPDATE stock SET s_quantity = 62 WHERE s_i_id = 14040 AND s
_w_id = 1 |
| 10 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 1347 WHERE w_id = 1
|
| 11 | tpcc | localhost | tpcc | Execute | 0 | statistics | SELECT count(*) FROM stock WHERE s_w_id = 1 AND s_i_id = 96
265 AND s_quantity < 19 |
| 12 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 2773 WHERE w_id = 1
|
| 13 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 2927 WHERE w_id = 1
|
| 14 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE stock SET s_quantity = 5 WHERE s_i_id = 89835 AND s_
w_id = 1 |
| 15 | tpcc | localhost | tpcc | Query | 0 | starting | commit
|
| 16 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE order_line SET ol_delivery_d = '2014-09-20 16:29:37'
WHERE ol_o_id = 2310 AND ol_d_id = 2 AND |
| 17 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 3326 WHERE w_id = 1
|
| 18 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 1965 WHERE w_id = 1
|
| 19 | tpcc | localhost | tpcc | Execute | 0 | optimizing | SELECT count(*) FROM stock WHERE s_w_id = 1 AND s_i_id = 78
08 AND s_quantity < 12 |
| 20 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 4738 WHERE w_id = 1
|
| 21 | tpcc | localhost | tpcc | Sleep | 0 | | NULL
|
| 22 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 925 WHERE w_id = 1
|
| 23 | tpcc | localhost | tpcc | Sleep | 0 | | NULL
|
| 24 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 1413 WHERE w_id = 1
|
| 25 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 3134 WHERE w_id = 1
|
| 26 | tpcc | localhost | tpcc | Execute | 0 | Writing to net | INSERT INTO order_line (ol_o_id, ol_d_id, ol_w_id, ol_numbe
r, ol_i_id, ol_supply_w_id, ol_quantity, |
| 27 | tpcc | localhost | tpcc | Execute | 0 | updating | UPDATE warehouse SET w_ytd = w_ytd + 1808 WHERE w_id = 1
|
+----+------+-----------+------+---------+------+----------------+------------------------------------------------------------
------------------------------------------+
21 rows in set (0.03 sec)
Query OK, 0 rows affected (0.02 sec)
+----+------+-----------+------+---------+------+-------------+---------------------------------------------------------------
---------------------+
| Id | User | Host | db | Command | Time | State | Info
|
+----+------+-----------+------+---------+------+-------------+---------------------------------------------------------------
---------------------+
| 7 | root | localhost | NULL | Query | 0 | starting | SHOW PROCESSLIST
|
| 11 | tpcc | localhost | tpcc | Killed | 0 | System lock | SELECT count(*) FROM stock WHERE s_w_id = 1 AND s_i_id = 32770
AND s_quantity < 19 |
| 15 | tpcc | localhost | tpcc | Killed | 0 | starting | commit
|
+----+------+-----------+------+---------+------+-------------+---------------------------------------------------------------
---------------------+
3 rows in set (0.00 sec)
オフラインモードに設定したあと、クエリー(not トランザクション)が終了したタイミングでクライアントは切断される。 切断されたクライアントで更に操作をしようとすると、フツーにError: 2006 "MySQL Server has gone away"が出力される(wait_timeoutとかで切断されたときといっしょ)
..
payment 3:1
2006, HY000, MySQL server has gone away
payment 3:1
2006, HY000, MySQL server has gone away
..
tpcc_startは起動時にセッション確保してそのままずっとそれでトラフィックをかけ続けるので、セッションをつなぎ直さないので、これがどばーとで続ける。
新しくつなぎ直そうとすると、
# mysql -utpcc -p tpcc
Enter password:
ERROR 1917 (HY000): The server is currently in offline mode
# mysql -uroot -p tpcc
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 30
Server version: 5.7.5-m15-log MySQL Community Server (GPL)
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
SUPERでないユーザーはError: 1917でエラーが返り、スーパーユーザーはそのまま接続できる。max_connection= 1みたいに2セッションしかメンテ用に使えないとか(スーパーユーザー全体で+1セッションなので、1本スーパーユーザーで入ると他のスーパーユーザーも入れない)そんなこともない。
オフラインモードに入れてもポートのLISTENはそのままなので、TCPで3306を叩くだけの死活監視は生きてしまうことくらいがアレだけど、LVSとか手前で切り離せばそれでもたぶんOK。
mysqladmin pingはエラーを出力するけど戻り値は0だった。FR出そうかな。
# mysqladmin -utpcc -p ping
Enter password:
mysqladmin: connect to server at 'localhost' failed
error: 'The server is currently in offline mode'
# echo $?
0
# mysqladmin -uroot -p ping
Enter password:
mysqld is alive
# echo $?
0