Quantcast
Channel: 日々の覚書
Viewing all articles
Browse latest Browse all 581

MySQL Fabricつらい(mysqlコマンドラインクライアントにHA切り替え機能を実装する編)

$
0
0
Connector/CでマスタースレーブHA打ち分け編の応用で、mysqlコマンドラインクライアントにHA打ち分け機能を追加してみました。

パッチはこんな感じ。MySQL 5.7.5-m15のmysqlコマンドラインクライアントベースだけど、labs版のConnector/Cが5.6をベースにしてるっぽい気配がして、おとなしく5.6のコマンドラインクライアントベースにすればよかったかも。。


*** client/mysql.cc.orig 2014-09-18 22:36:41.000000000 +0900
--- client/mysql.cc 2014-11-14 16:28:49.499593984 +0900
***************
*** 76,82 ****
using std::min;
using std::max;

! const char *VER= "14.14";

/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
--- 76,82 ----
using std::min;
using std::max;

! const char *VER= "14.14-fabric";

/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
***************
*** 188,193 ****
--- 188,195 ----
static char delimiter[16]= DEFAULT_DELIMITER;
static size_t delimiter_length= 1;
unsigned short terminal_width= 80;
+ static char *opt_fabric_group= 0, *opt_fabric_user= 0;
+ static char *opt_fabric_password= 0;

#if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)
static char *shared_memory_base_name=0;
***************
*** 255,261 ****
com_notee(String *str, char*), com_charset(String *str,char*),
com_prompt(String *str, char*), com_delimiter(String *str, char*),
com_warnings(String *str, char*), com_nowarnings(String *str, char*),
! com_resetconnection(String *str, char*);

#ifdef USE_POPEN
static int com_nopager(String *str, char*), com_pager(String *str, char*),
--- 257,264 ----
com_notee(String *str, char*), com_charset(String *str,char*),
com_prompt(String *str, char*), com_delimiter(String *str, char*),
com_warnings(String *str, char*), com_nowarnings(String *str, char*),
! com_resetconnection(String *str, char*),
! com_fabric(String *str, char*);

#ifdef USE_POPEN
static int com_nopager(String *str, char*), com_pager(String *str, char*),
***************
*** 322,327 ****
--- 325,332 ----
#ifdef USE_POPEN
{ "edit", 'e', com_edit, 0, "Edit command with $EDITOR."},
#endif
+ // Added by yoku0825.
+ { "fabric", 'F', com_fabric, 1, "Choose fabric opt group." },
{ "ego", 'G', com_ego, 0,
"Send command to mysql server, display result vertically."},
{ "exit", 'q', com_quit, 0, "Exit mysql. Same as quit."},
***************
*** 1833,1838 ****
--- 1838,1855 ----
"password sandbox mode.",
&opt_connect_expired_password, &opt_connect_expired_password, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
+ // Added by yoku0825.
+ {"fabric-group", 0,
+ "fabric group", &opt_fabric_group, &opt_fabric_group, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"fabric-user", 0,
+ "Real user name which is used to connect through MySQL Fabric",
+ &opt_fabric_user, &opt_fabric_user, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"fabric-password", 0,
+ "Real password which is used to connect through MySQL Fabric",
+ &opt_fabric_password, &opt_fabric_password, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};

***************
*** 4883,4888 ****
--- 4900,4909 ----
}
#endif

+ // Added by yoku0825.
+ if (opt_fabric_group)
+ mysql_options(&mysql, MYSQL_OPT_USE_FABRIC, NULL);
+
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_STATEMENTS))
***************
*** 4898,4903 ****
--- 4919,4932 ----
return -1; // Retryable
}

+ // Added by yoku0825.
+ if (opt_fabric_group)
+ {
+ mysql_options(&mysql, FABRIC_OPT_GROUP, opt_fabric_group);
+ mysql_options4(&mysql, FABRIC_OPT_GROUP_CREDENTIALS, opt_fabric_user, opt_fabric_password);
+ mysql_options(&mysql, FABRIC_OPT_DEFAULT_MODE, "rw");
+ }
+
#ifdef _WIN32
/* Convert --execute buffer from UTF8MB4 to connection character set */
if (!execute_buffer_conversion_done++ &&
***************
*** 5763,5765 ****
--- 5792,5812 ----
}
return error;
}
+
+ // Added by yoku0825.
+ static int com_fabric(String *buffer __attribute__((unused)),
+ char *line __attribute__((unused)))
+ {
+ char *ptr=strchr(line, '');
+ char *new_fabric_opt_mode= my_strdup(PSI_NOT_INSTRUMENTED,
+ ptr ? ptr + 1 : 0, MYF(MY_WME));
+
+ if (strcmp(new_fabric_opt_mode, "ro") || strcmp(new_fabric_opt_mode, "rw"))
+ {
+ mysql_options(&mysql, FABRIC_OPT_DEFAULT_MODE, new_fabric_opt_mode);
+ tee_fprintf(stdout, "Current FABRIC_OPT_DEFAULT_MODE is %s\n", new_fabric_opt_mode);
+ }
+ else
+ tee_fprintf(stdout, "Failed to change FABRIC_OPT_DEFAULT_MODE. Only 'ro' and 'rw' are permitted.\n", new_fabric_opt_mode);
+ return 0;
+ }

取り敢えずConnector/CからMySQL Fabricでマスタースレーブの打ち分けをするのに必要なパラメーターはグループ名, 本物のノードに接続するユーザー名とパスワードくらいなので、オプション(--fabric-group, --fabric-user, --fabric-password)で受け取るようにする。

あとはmysql_real_connectを読んでいるsql_real_connectの中で、--fabric-groupが渡されてたらMYSQL_OPT_USE_FABRICを押し込んで、接続後にFABRIC_OPT_GROUP, FABRIC_OPT_GROUP_CREDENTIALS, FABRIC_OPT_DEFAULT_MODEを押し込むという感じ。コンソールの中でrwとroを切り替えるためにcom_fabricも追加。

実際こんな感じ。


$ client/mysql -P32275 -h127.0.0.1 -uadmin -pxxxx --protocol=tcp ## FabricサーバーのMySQLプロトコルの口に、FABRICモードでなく接続
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 53
Server version: 1.5.3-fabric -- Fabricサーバーのバージョンが出てくる

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> SELECT @@port; -- Fabricサーバーにつながってるだけなので何も出てこない
Query OK, 0 rows affected (0.00 sec)


$ client/mysql -P32275 -h127.0.0.1 -uadmin -pxxxx --protocol=tcp --fabric-group=my_first_fabric --fabric-user=msandbox --fabric-password=msandbox
mysql: [Warning] Using a password on the command line interface can be insecure.
Using Fabric for MYSQL connection -- FABRIC経由でつながると(今のところ必ず)これが出る。
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 167034
Server version: 5.6.21-log Source distribution -- MySQLサーバーのバージョン

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> SELECT @@port; -- デフォルトはrw側
+--------+
| @@port |
+--------+
| 20886 |
+--------+
1 row in set (0.00 sec)

mysql> fabric ro -- "fabric {ro|rw}"で切り替えられるようにした
Current FABRIC_OPT_DEFAULT_MODE is ro

mysql> SELECT @@port; -- こっちがro側
+--------+
| @@port |
+--------+
| 20887 |
+--------+
1 row in set (0.00 sec)

mysql> \F rw -- "\Fはfabricのシノニム"
Current FABRIC_OPT_DEFAULT_MODE is rw

mysql> SELECT @@port;
+--------+
| @@port |
+--------+
| 20886 |
+--------+
1 row in set (0.00 sec)

前回使ってたFABRIC_OPT_MODEの方は、mysql_optionsしたすぐ次のクエリー(ただし、トランザクションの途中であれば考慮してくれる)でしか有効でないらしいので、FABRIC_OPT_DEFAULT_modeを使うようにしてみた。

ちなみに、Fabricサーバー(mysqlfabric)のMySQLプロトコルの口にログインしただけの状態でstatusとか叩くとコマンドラインクライアントが落ちる。

MySQL Bugs: #74340: Crash on status query when connected to fabric

--fabric-groupや--fabric-user, --fabric-passwordが間違ってて上手くバックエンドにつなぎにいけない場合も(クライアントがコア吐いて)これまた落ちるんだけど、取り敢えず仕様ということで。。

こんな感じで誰か DBD::mysqlにMySQL Fabricをポートしてくだしあ。


【2014/11/17 11:33】
FABRIC_OPT_MODEの動きについてこっちに追記。
http://yoku0825.blogspot.jp/2014/11/mysql-fabricfabricoptmode-ro.html

Viewing all articles
Browse latest Browse all 581

Trending Articles