From 3b3799889eb3aa03fad20e024b16c34542e3d0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 29 Jun 2017 11:52:16 +0300 Subject: [PATCH] MXS-852: Fix PS storage when locker to the master When the router session is locked to the master, the storage of prepared statements is not necessary as no other server can be used. The ID sent by the client can be used without modification as it will always be the same on the master. --- .../readwritesplit/rwsplit_route_stmt.cc | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/server/modules/routing/readwritesplit/rwsplit_route_stmt.cc b/server/modules/routing/readwritesplit/rwsplit_route_stmt.cc index 9c9a196de..19e46aeb4 100644 --- a/server/modules/routing/readwritesplit/rwsplit_route_stmt.cc +++ b/server/modules/routing/readwritesplit/rwsplit_route_stmt.cc @@ -125,19 +125,33 @@ route_target_t get_target_type(RWSplitSession *rses, GWBUF *buffer, * eventually to master */ - if (*command == MYSQL_COM_QUERY && - qc_get_operation(buffer) == QUERY_OP_EXECUTE) + if (rses->target_node && rses->target_node == rses->current_master) { - std::string id = get_text_ps_id(buffer); - *type = rses->ps_manager.get_type(id); - } - else if (is_ps_command(*command)) - { - *stmt_id = get_internal_ps_id(rses, buffer); - *type = rses->ps_manager.get_type(*stmt_id); - } + /** The session is locked to the master */ + route_target = TARGET_MASTER; - route_target = get_route_target(rses, *command, *type, buffer->hint); + if (qc_query_is_type(*type, QUERY_TYPE_PREPARE_NAMED_STMT) || + qc_query_is_type(*type, QUERY_TYPE_PREPARE_STMT)) + { + gwbuf_set_type(buffer, GWBUF_TYPE_COLLECT_RESULT); + } + } + else + { + if (*command == MYSQL_COM_QUERY && + qc_get_operation(buffer) == QUERY_OP_EXECUTE) + { + std::string id = get_text_ps_id(buffer); + *type = rses->ps_manager.get_type(id); + } + else if (is_ps_command(*command)) + { + *stmt_id = get_internal_ps_id(rses, buffer); + *type = rses->ps_manager.get_type(*stmt_id); + } + + route_target = get_route_target(rses, *command, *type, buffer->hint); + } } else { @@ -167,10 +181,12 @@ bool route_single_stmt(RWSplit *inst, RWSplitSession *rses, GWBUF *querybuf, con uint8_t command = info.command; uint32_t qtype = info.type; route_target_t route_target = info.target; + bool not_locked_to_master = !rses->target_node || rses->target_node != rses->current_master; - if (is_ps_command(command)) + if (is_ps_command(command) && not_locked_to_master) { - /** Replace the client statement ID with our internal one */ + /** Replace the client statement ID with our internal one only if the + * target node is not the current master */ replace_binary_ps_id(querybuf, stmt_id); } @@ -221,7 +237,7 @@ bool route_single_stmt(RWSplit *inst, RWSplitSession *rses, GWBUF *querybuf, con ss_dassert(!store_stmt || TARGET_IS_SLAVE(route_target)); succp = handle_got_target(inst, rses, querybuf, target, store_stmt); - if (succp && command == MYSQL_COM_STMT_EXECUTE) + if (succp && command == MYSQL_COM_STMT_EXECUTE && not_locked_to_master) { /** Track the targets of the COM_STMT_EXECUTE statements. This * information is used to route all COM_STMT_FETCH commands @@ -552,17 +568,13 @@ route_target_t get_route_target(RWSplitSession *rses, uint8_t command, mxs_target_t use_sql_variables_in = rses->rses_config.use_sql_variables_in; int target = TARGET_UNDEFINED; - if (rses->target_node && rses->target_node == rses->current_master) - { - target = TARGET_MASTER; - } /** * Prepared statements preparations should go to all servers */ - else if (qc_query_is_type(qtype, QUERY_TYPE_PREPARE_STMT) || - qc_query_is_type(qtype, QUERY_TYPE_PREPARE_NAMED_STMT) || - command == MYSQL_COM_STMT_CLOSE || - command == MYSQL_COM_STMT_RESET) + if (qc_query_is_type(qtype, QUERY_TYPE_PREPARE_STMT) || + qc_query_is_type(qtype, QUERY_TYPE_PREPARE_NAMED_STMT) || + command == MYSQL_COM_STMT_CLOSE || + command == MYSQL_COM_STMT_RESET) { target = TARGET_ALL; }