2014年11月18日火曜日

MySQL Fabricつらい(Fabricサーバー上のMySQLプロトコルの口でFabricのAPIが呼べる編)

もともとは、mysqlコマンドラインクライアントにHA切り替え機能を実装する編 でいじってたクライアントにもう少しパラメーターを突っ込もうとか Fabricサーバー上でstatusコマンド叩くとmysqlコマンドラインクライアントがクラッシュする件 を直したいとかそんなことを考えてソースを読んでいたときのこと。

mysql-utilities-1.5.3/mysql/fabric/protocols/mysqlrpc.py のMySQLRPCRequestHandler.handleあたりの中で
 925             # Handle CALL
 926             if CHECK_CALL.match(data):
 927                 call_match = PARSE_CALL.match(data)
 928                 if call_match:
 929                     self._handle_call(call_match)
 930                 else:
 931                     self.send_syntax_error()
 932                 continue
 933
 934             # Handle SHOW CREATE PROCEDURE
 935             if CHECK_SHOW_CREATE_PROC.match(data):
 936                 showproc_match = PARSE_SHOW_CREATE_PROC.match(data)
 937                 if showproc_match:
 938                     self._handle_show_create_procedure(showproc_match)
 939                 else:
 940                     self.send_syntax_error()
 941                 continue
 942
 943             # Handle INFORMATION_SCHEMA.ROUTINES
 944             is_routines_match = PARSE_IS_ROUTINES.match(data)
 945             if is_routines_match:
 946                 self._handle_information_schema_routines(is_routines_match)
 947                 continue
 948
 949             # Handle SET
 950             set_match = PARSE_SET.match(data)
 951             if set_match and set_match.group(1).lower() in ('format',):
 952                 format = dequote(set_match.group(2).strip()).strip().lower()
 953                 if format not in ('json',):
 954                     self.send_error(
 955                         errorcode.ER_LOCAL_VARIABLE,
 956                         "Format '{0}' is not supported".format(format),
 957                         "42000"
 958                     )
 959                 else:
 960                     _LOGGER.debug("Format set to %s", format)
 961                     self._format = format
 962
 963             # We accept anything else without doing anything
 964             self.send_packet(self.ok_packet())


なんか特定の文字列が来た時だけ別ハンドルにしているように見える。
さかのぼってこのPARSE_*の中身を覗いてみると、
  57 # Regular expression getting group, command and the arguments as a string
  58 CHECK_CALL = re.compile(
  59     r"""^CALL\s*""", re.IGNORECASE
  60 )
  61 PARSE_CALL = re.compile(
  62     r"""CALL\s+(\w+)\.(\w+)\s*\((.*)\)"""
  63     r"""(?=(?:[^"']*["'][^"']*["'])*[^"']*$)""", re.IGNORECASE
  64 )
  65 PARSE_CALL_ARGS = re.compile(
  66     r""",(?=(?:[^"']*["'][^"']*["'])*[^"']*$)"""
  67 )
  68 PARSE_CALL_KWARG = re.compile(
  69     r"""=(?=(?:[^"']*["'][^"']*["'])*[^"']*$)"""
  70 )
  71
  72 # Regular expression for SHOW CREATE PROCEDURE
  73 CHECK_SHOW_CREATE_PROC = re.compile(
  74     r"""^SHOW\s+CREATE\s+PROCEDURE\s*""", re.IGNORECASE
  75 )
  76 PARSE_SHOW_CREATE_PROC = re.compile(
  77     r"""SHOW\s+CREATE\s+PROCEDURE\s+(\w+).(\w+)$""", re.IGNORECASE
  78 )
  79
  80 # Regular expression for INFORMATION_SCHEMA.ROUTINES
  81 PARSE_IS_ROUTINES = re.compile(
  82     r"""SELECT\s+(.*)\s+FROM\s+INFORMATION_SCHEMA.ROUTINES\s*(.*)""",
  83     re.IGNORECASE
  84 )
  85
  86 # Regular expression getting SET statements
  87 PARSE_SET = re.compile(
  88     r"""SET\s+(\w+)\s*=(.*)""", re.IGNORECASE
  89 )

このあたりのクエリーは無視せずに返してくれるらしい。

$ client/mysql -P 32275 -u admin -p --protocol=tcp
mysql> SELECT * FROM information_schema.routines;
+----------------------------+-----------------+----------------+----------------------+----------------+
| SPECIFIC_NAME              | ROUTINE_CATALOG | ROUTINE_SCHEMA | ROUTINE_NAME         | ROUTINE_TYPE   |
+----------------------------+-----------------+----------------+----------------------+----------------+
| statistics.node            | fabric          | statistics     | node                 | FABRIC_COMMAND |
| statistics.group           | fabric          | statistics     | group                | FABRIC_COMMAND |
| statistics.procedure       | fabric          | statistics     | procedure            | FABRIC_COMMAND |
| group.activate             | fabric          | group          | activate             | FABRIC_COMMAND |
| group.description          | fabric          | group          | description          | FABRIC_COMMAND |
| group.deactivate           | fabric          | group          | deactivate           | FABRIC_COMMAND |
| group.create               | fabric          | group          | create               | FABRIC_COMMAND |
| group.remove               | fabric          | group          | remove               | FABRIC_COMMAND |
| group.add                  | fabric          | group          | add                  | FABRIC_COMMAND |
| group.health               | fabric          | group          | health               | FABRIC_COMMAND |
| group.lookup_servers       | fabric          | group          | lookup_servers       | FABRIC_COMMAND |
| group.destroy              | fabric          | group          | destroy              | FABRIC_COMMAND |
| group.demote               | fabric          | group          | demote               | FABRIC_COMMAND |
| group.promote              | fabric          | group          | promote              | FABRIC_COMMAND |
| group.lookup_groups        | fabric          | group          | lookup_groups        | FABRIC_COMMAND |
| dump.fabric_nodes          | fabric          | dump           | fabric_nodes         | FABRIC_COMMAND |
| dump.shard_index           | fabric          | dump           | shard_index          | FABRIC_COMMAND |
| dump.sharding_information  | fabric          | dump           | sharding_information | FABRIC_COMMAND |
| dump.servers               | fabric          | dump           | servers              | FABRIC_COMMAND |
| dump.shard_tables          | fabric          | dump           | shard_tables         | FABRIC_COMMAND |
| dump.shard_maps            | fabric          | dump           | shard_maps           | FABRIC_COMMAND |
| manage.teardown            | fabric          | manage         | teardown             | FABRIC_COMMAND |
| manage.stop                | fabric          | manage         | stop                 | FABRIC_COMMAND |
| manage.setup               | fabric          | manage         | setup                | FABRIC_COMMAND |
| manage.ping                | fabric          | manage         | ping                 | FABRIC_COMMAND |
| manage.start               | fabric          | manage         | start                | FABRIC_COMMAND |
| manage.logging_level       | fabric          | manage         | logging_level        | FABRIC_COMMAND |
| server.set_mode            | fabric          | server         | set_mode             | FABRIC_COMMAND |
| server.clone               | fabric          | server         | clone                | FABRIC_COMMAND |
| server.list                | fabric          | server         | list                 | FABRIC_COMMAND |
| server.set_weight          | fabric          | server         | set_weight           | FABRIC_COMMAND |
| server.lookup_uuid         | fabric          | server         | lookup_uuid          | FABRIC_COMMAND |
| server.set_status          | fabric          | server         | set_status           | FABRIC_COMMAND |
| server.destroy             | fabric          | server         | destroy              | FABRIC_COMMAND |
| server.create              | fabric          | server         | create               | FABRIC_COMMAND |
| role.list                  | fabric          | role           | list                 | FABRIC_COMMAND |
| user.roles                 | fabric          | user           | roles                | FABRIC_COMMAND |
| user.usercommand           | fabric          | user           | usercommand          | FABRIC_COMMAND |
| user.list                  | fabric          | user           | list                 | FABRIC_COMMAND |
| user.add                   | fabric          | user           | add                  | FABRIC_COMMAND |
| user.password              | fabric          | user           | password             | FABRIC_COMMAND |
| user.delete                | fabric          | user           | delete               | FABRIC_COMMAND |
| threat.report_error        | fabric          | threat         | report_error         | FABRIC_COMMAND |
| threat.report_failure      | fabric          | threat         | report_failure       | FABRIC_COMMAND |
| provider.unregister        | fabric          | provider       | unregister           | FABRIC_COMMAND |
| provider.register          | fabric          | provider       | register             | FABRIC_COMMAND |
| provider.list              | fabric          | provider       | list                 | FABRIC_COMMAND |
| sharding.list_definitions  | fabric          | sharding       | list_definitions     | FABRIC_COMMAND |
| sharding.remove_definition | fabric          | sharding       | remove_definition    | FABRIC_COMMAND |
| sharding.move_shard        | fabric          | sharding       | move_shard           | FABRIC_COMMAND |
| sharding.disable_shard     | fabric          | sharding       | disable_shard        | FABRIC_COMMAND |
| sharding.remove_table      | fabric          | sharding       | remove_table         | FABRIC_COMMAND |
| sharding.split_shard       | fabric          | sharding       | split_shard          | FABRIC_COMMAND |
| sharding.create_definition | fabric          | sharding       | create_definition    | FABRIC_COMMAND |
| sharding.add_shard         | fabric          | sharding       | add_shard            | FABRIC_COMMAND |
| sharding.add_table         | fabric          | sharding       | add_table            | FABRIC_COMMAND |
| sharding.lookup_table      | fabric          | sharding       | lookup_table         | FABRIC_COMMAND |
| sharding.enable_shard      | fabric          | sharding       | enable_shard         | FABRIC_COMMAND |
| sharding.remove_shard      | fabric          | sharding       | remove_shard         | FABRIC_COMMAND |
| sharding.list_tables       | fabric          | sharding       | list_tables          | FABRIC_COMMAND |
| sharding.prune_shard       | fabric          | sharding       | prune_shard          | FABRIC_COMMAND |
| sharding.lookup_servers    | fabric          | sharding       | lookup_servers       | FABRIC_COMMAND |
| snapshot.destroy           | fabric          | snapshot       | destroy              | FABRIC_COMMAND |
| snapshot.create            | fabric          | snapshot       | create               | FABRIC_COMMAND |
| event.trigger              | fabric          | event          | trigger              | FABRIC_COMMAND |
| event.wait_for_procedures  | fabric          | event          | wait_for_procedures  | FABRIC_COMMAND |
+----------------------------+-----------------+----------------+----------------------+----------------+
66 rows in set (0.00 sec)


おお、ホントだ。
これ、バッキングストアやファームのMySQLサーバーの上ではなくFabricサーバーの上なので、たとえば他のテーブルとかは存在しない。というかたぶんクエリーを握りつぶしてる。

mysql> SELECT * FROM information_schema.tables;
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW DATABASES;
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW GLOBAL VARIABLES;
Query OK, 0 rows affected (0.00 sec)


SHOW CREATE PROCEDUREでプロシージャを見ると、

mysql> SHOW CREATE PROCEDURE group.health\G
*************************** 1. row ***************************
fabric_help: group health group_id

Check if any server within a group has failed and report health
information.

It returns a dictionary where keys are the servers' uuids and the
values are dictionaries which have the following keys:

* is_alive - whether it is possible to access the server or not.     *
status - PRIMARY, SECONDARY, SPARE or FAULTY.     * threads -
Information on the replication threads.
1 row in set (0.00 sec)


簡単なusageが表示される。

mysql> CALL group.health();
+--------------------------------------+-----+-----------------------------------------------+
| fabric_uuid                          | ttl | message                                       |
+--------------------------------------+-----+-----------------------------------------------+
| 5ca1ab1e-a007-feed-f00d-cab3fe13249e |   1 | execute() takes exactly 2 arguments (1 given) |
+--------------------------------------+-----+-----------------------------------------------+
1 row in set (0.01 sec)


ありゃ、引数の数が足りないらしい。や、それこそusageのSHOW CREATE PROCEDUREに書けよ。
取り敢えずたぶんFabric Groupが足りないんだと思うので渡してみようか。

mysql> CALL group.health('my_first_fabric');
+--------------------------------------+-----+---------+
| fabric_uuid                          | ttl | message |
+--------------------------------------+-----+---------+
| 5ca1ab1e-a007-feed-f00d-cab3fe13249e |   1 | NULL    |
+--------------------------------------+-----+---------+
1 row in set (0.14 sec)

+--------------------------------------+----------+-----------+----------------+-------------------+----------------+-----------------+----------+-----------+
| uuid                                 | is_alive | status    | is_not_running | is_not_configured | io_not_running | sql_not_running | io_error | sql_error |
+--------------------------------------+----------+-----------+----------------+-------------------+----------------+-----------------+----------+-----------+
| 47cf54df-63fc-11e4-942e-fa163e020fd0 |        1 | PRIMARY   |              0 |                 0 |              0 |               0 | False    | False     |
| 4b7036a9-63fc-11e4-942e-fa163e020fd0 |        1 | SECONDARY |              0 |                 0 |              0 |               0 | False    | False     |
+--------------------------------------+----------+-----------+----------------+-------------------+----------------+-----------------+----------+-----------+
2 rows in set (0.14 sec)

Empty set (0.14 sec)


うむ。
こんなこともできるんだ、ってことは認識したんだが、

ドキュメントはよ

0 件のコメント :

コメントを投稿