279 lines
12 KiB
C++
279 lines
12 KiB
C++
/**
|
|
* @file bug699.cpp regression case for bug 699 ( "rw-split sensitive to order of terms in field list of
|
|
* SELECT (round 2)" )
|
|
*
|
|
* - compare @@hostname from "select @@wsrep_node_name, @@hostname" and "select @@hostname,
|
|
*@@wsrep_node_name"
|
|
* - comapre @@server_id from "select @@wsrep_node_name, @@server_id" and "select @@server_id,
|
|
*@@wsrep_node_name"
|
|
*/
|
|
|
|
/*
|
|
* Kolbe Kegel 2015-01-16 18:38:15 UTC
|
|
* I opened bug #509 some time ago, but that bug was handled specifically for the case of last_insert_id().
|
|
* The crux of that bug still exists in 1.0.4 GA:
|
|
*
|
|
* [root@max1 ~]# mysql -h 127.0.0.1 -P 4006 -u maxuser -pmaxpwd -e 'select @@hostname, @@wsrep_node_name;
|
|
* select @@wsrep_node_name, @@hostname;'
|
|
+------------+-------------------+
|
|
| @@hostname | @@wsrep_node_name |
|
|
+------------+-------------------+
|
|
| db2 | db2 |
|
|
+------------+-------------------+
|
|
+-------------------+------------+
|
|
| @@wsrep_node_name | @@hostname |
|
|
+-------------------+------------+
|
|
| db3 | db3 |
|
|
+-------------------+------------+
|
|
|
|
|
| In a single connection, fetching the values of the same two system variables results in the query being
|
|
|routed differently depending on the order of the variables.
|
|
|
|
|
| Is there some set of variables that should always be routed to the master for some reason? If so, that
|
|
|should be documented.
|
|
|
|
|
| Regardless, the order of terms in the SELECT list should not have any effect on query routing.
|
|
| Comment 1 Vilho Raatikka 2015-01-16 22:33:38 UTC
|
|
| @@wsrep_node_name can be resolved only in backend, MaxScale doesn't know about it. As a consequence, Since
|
|
|MaxScale doesn't know what it is it takes the safe bet and routes it to master.
|
|
| Comment 2 Kolbe Kegel 2015-01-16 22:35:13 UTC
|
|
| What does "(In reply to comment #1)
|
|
| > @@wsrep_node_name can be resolved only in backend, MaxScale doesn't know
|
|
| > about it. As a consequence, Since MaxScale doesn't know what it is it takes
|
|
| > the safe bet and routes it to master.
|
|
|
|
|
| What do you mean by "resolved only in backend" and "MaxScale doesn't know about it"?
|
|
|
|
|
| How is @@wsrep_node_name different in that respect from any other server variable that could be different
|
|
|on any given backend?
|
|
| Comment 3 Vilho Raatikka 2015-01-16 23:01:31 UTC
|
|
| (In reply to comment #2)
|
|
| > What does "(In reply to comment #1)
|
|
| > > @@wsrep_node_name can be resolved only in backend, MaxScale doesn't know
|
|
| > > about it. As a consequence, Since MaxScale doesn't know what it is it takes
|
|
| > > the safe bet and routes it to master.
|
|
| >
|
|
| > What do you mean by "resolved only in backend" and "MaxScale doesn't know
|
|
| > about it"?
|
|
| >
|
|
| > How is @@wsrep_node_name different in that respect from any other server
|
|
| > variable that could be different on any given backend?
|
|
|
|
|
| MaxScale doesn't know that there is such system variable as @@wsrep_node_name. In my understanding the
|
|
|reason is that the embedded MariaDB server doesn't have Galera's patch. Thus the variable is unknown.
|
|
| Comment 4 Kolbe Kegel 2015-01-16 23:03:13 UTC
|
|
| > >
|
|
| > > How is @@wsrep_node_name different in that respect from any other server
|
|
| > > variable that could be different on any given backend?
|
|
| >
|
|
| > MaxScale doesn't know that there is such system variable as
|
|
| > @@wsrep_node_name. In my understanding the reason is that the embedded
|
|
| > MariaDB server doesn't have Galera's patch. Thus the variable is unknown.
|
|
|
|
|
| Ahh, right. That sounds familiar. But it's still quite strange that the order of variables in the SELECT
|
|
|statement is meaningful, isn't it?
|
|
| Comment 5 Vilho Raatikka 2015-01-16 23:09:47 UTC
|
|
| (In reply to comment #4)
|
|
| > > >
|
|
| > > > How is @@wsrep_node_name different in that respect from any other server
|
|
| > > > variable that could be different on any given backend?
|
|
| > >
|
|
| > > MaxScale doesn't know that there is such system variable as
|
|
| > > @@wsrep_node_name. In my understanding the reason is that the embedded
|
|
| > > MariaDB server doesn't have Galera's patch. Thus the variable is unknown.
|
|
| >
|
|
| > Ahh, right. That sounds familiar. But it's still quite strange that the
|
|
| > order of variables in the SELECT statement is meaningful, isn't it?
|
|
|
|
|
| The effectiveness of atrribute order in SELECT clause is a bug which is fixed in
|
|
|http://bugs.skysql.com/show_bug.cgi?id=694 .
|
|
|
|
|
| MaxScale's inability to detect different system variables is slightly problematic as well but haven't
|
|
|really concentrated on finding a decent solution to it yet. It might, however, be necessary.
|
|
| Comment 6 Vilho Raatikka 2015-01-16 23:55:56 UTC
|
|
| Attribute order effectiveness is fixed in http://bugs.skysql.com/show_bug.cgi?id=694
|
|
|
|
|
| Inability to detect Galera's system variables is hard to overcome since Galera patch doesn't work with
|
|
|embedded library and embedded library doesn't know Galera's system variables.
|
|
| Comment 7 Vilho Raatikka 2015-01-17 09:38:09 UTC
|
|
| Appeared that MariaDB parsing end result depends on the order of [known,unknown] system variable pair in
|
|
|the query.
|
|
|
|
|
| There was similar-looking bug in query_classifier before which hide this one. However, debugging and
|
|
|examining the resulting thd and lex for the following queries shows that thd->free_list is non-empty if
|
|
|@@hostname (known variable) is before @@wsrep_node_name. If @@wsrep_node_name is first on the attribute list
|
|
|the resulting thd->free_list==NULL.
|
|
| In the former case resulting query type is QUERY_TYPE_SYSVAR_READ (routed to slaves) and in the latter
|
|
|case it is unknown (routed to master).
|
|
|
|
|
| 1. select @@wsrep_node_name, @@hostname;
|
|
| 2. select @@hostname, @@wsrep_node_name;
|
|
|
|
|
| Both queries produce similar response but routing them to master only limits scalability.
|
|
| Comment 8 Mark Riddoch 2015-01-28 08:39:25 UTC
|
|
| Raised this with the server team as the issue is related to the behaviour of the parser in the embedded
|
|
|server. System variables are resolved at parse time, unknown variables result in a parse error normally,
|
|
|however this order dependency is slightly puzzling.
|
|
| Comment 9 Mark Riddoch 2015-02-13 10:06:08 UTC
|
|
| Hi Sergei,
|
|
|
|
|
| we have an interesting bug in MaxScale related to parsing. If we try to parse the query
|
|
|
|
|
| select @@wsrep_node_name;
|
|
|
|
|
| Using the embedded server we link with we do not get a parse tree. A select of other system variables
|
|
|works. I guess the parser is resolving the name of the variable rather than leaving it to the execution
|
|
|phase. Since we do not have Galera this variable is unknown. What is even more strange is that if we have a
|
|
|query of the form
|
|
|
|
|
| select @@hostname, @@wsrep_node_name;
|
|
|
|
|
| We do get a parse tree, but reversing the order of the select we again fail to get a parse tree with the
|
|
|query
|
|
|
|
|
| select @@wsrep_node_name, @@hostname;
|
|
|
|
|
| For our purposes we would ideally like to disable the resolving of the variable name at parse time, since
|
|
|that would give us flexibility with regard to new variables being introduced in the servers. Do you know if
|
|
|this is possible or if there is some easy fix we can do to the MariaDB parser that will help us here?
|
|
|
|
|
| For your reference the MaxScale bug report can be found here http://bugs.skysql.com/show_bug.cgi?id=699
|
|
|
|
|
|
|
|
| Thanks
|
|
| Mark
|
|
| Comment 10 Mark Riddoch 2015-02-13 10:08:34 UTC
|
|
| Hi, Mark!
|
|
|
|
|
| On Jan 28, Mark Riddoch wrote:
|
|
| > Hi Sergei,
|
|
| >
|
|
| > we have an interesting bug in MaxScale related to parsing. If we try
|
|
| > to parse the query
|
|
| >
|
|
| > select @@wsrep_node_name;
|
|
| >
|
|
| > Using the embedded server we link with we do not get a parse tree. A
|
|
| > select of other system variables works. I guess the parser is
|
|
| > resolving the name of the variable rather than leaving it to the
|
|
| > execution phase. Since we do not have Galera this variable is unknown.
|
|
|
|
|
| Right... That would be *very* difficult to fix, it'd require a pretty
|
|
| serious refactoring to get this out of the parser.
|
|
|
|
|
| > What is even more strange is that if we have a query of the form
|
|
| >
|
|
| > select @@hostname, @@wsrep_node_name;
|
|
| >
|
|
| > We do get a parse tree, but reversing the order of the select we again
|
|
| > fail to get a parse tree with the query
|
|
| >
|
|
| > select @@wsrep_node_name, @@hostname;
|
|
|
|
|
| That depends on what you call a "parse tree". Items of the select clause
|
|
| are stored in the thd->lex->current_select->item_list.
|
|
|
|
|
| For the first query, the list have 1 element, Item_func_get_system_var
|
|
| for @@hostname.
|
|
|
|
|
| For the second query the list has 0 elements. In both cases, I've
|
|
| examined the list in the debugger after MYSQLparse() returned.
|
|
|
|
|
| So apparently the parsing as aborted as soon as unknown variable is
|
|
| encountered.
|
|
|
|
|
| > For our purposes we would ideally like to disable the resolving of the
|
|
| > variable name at parse time, since that would give us flexibility with
|
|
| > regard to new variables being introduced in the servers. Do you know
|
|
| > if this is possible or if there is some easy fix we can do to the
|
|
| > MariaDB parser that will help us here?
|
|
|
|
|
| I don't see how you can do that from MaxScale.
|
|
| This looks like something that has to be fixed in the server.
|
|
| Perhaps - not sure - it'd be possible to introduce some "mode" for the
|
|
| parser where it doesn't check for valid variable names in certain
|
|
| contextes.
|
|
|
|
|
| Regards,
|
|
| Sergei
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <iostream>
|
|
#include "testconnections.h"
|
|
|
|
const char* sel1 = "select @@wsrep_node_name, @@hostname";
|
|
const char* sel2 = "select @@hostname, @@wsrep_node_name";
|
|
|
|
const char* sel3 = "select @@wsrep_node_name, @@server_id";
|
|
const char* sel4 = "select @@server_id, @@wsrep_node_name";
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
TestConnections* Test = new TestConnections(argc, argv);
|
|
Test->set_timeout(20);
|
|
|
|
Test->maxscales->connect_maxscale(0);
|
|
|
|
Test->tprintf("Trying \n");
|
|
|
|
char serverid1[1024];
|
|
char serverid2[1024];
|
|
|
|
if ((
|
|
find_field(Test->maxscales->conn_rwsplit[0],
|
|
sel3,
|
|
"@@server_id",
|
|
&serverid1[0])
|
|
!= 0 ) || (
|
|
find_field(Test->maxscales->conn_rwsplit[0],
|
|
sel4,
|
|
"@@server_id",
|
|
&serverid2[0])
|
|
!= 0 ))
|
|
{
|
|
Test->add_result(1, "@@server_id field not found!!\n");
|
|
delete Test;
|
|
exit(1);
|
|
}
|
|
else
|
|
{
|
|
Test->tprintf("'%s' to RWSplit gave @@server_id %s\n", sel3, serverid1);
|
|
Test->tprintf("'%s' directly to master gave @@server_id %s\n", sel4, serverid2);
|
|
Test->add_result(strcmp(serverid1, serverid2),
|
|
"server_id are different depending in which order terms are in SELECT\n");
|
|
}
|
|
|
|
if ((
|
|
find_field(Test->maxscales->conn_rwsplit[0],
|
|
sel1,
|
|
"@@hostname",
|
|
&serverid1[0])
|
|
!= 0 ) || (
|
|
find_field(Test->maxscales->conn_rwsplit[0],
|
|
sel2,
|
|
"@@hostname",
|
|
&serverid2[0])
|
|
!= 0 ))
|
|
{
|
|
Test->add_result(1, "@@hostname field not found!!\n");
|
|
delete Test;
|
|
exit(1);
|
|
}
|
|
else
|
|
{
|
|
Test->tprintf("'%s' to RWSplit gave @@hostname %s\n", sel1, serverid1);
|
|
Test->tprintf("'%s' to RWSplit gave @@hostname %s\n", sel2, serverid2);
|
|
Test->add_result(strcmp(serverid1, serverid2),
|
|
"hostname are different depending in which order terms are in SELECT\n");
|
|
}
|
|
|
|
Test->maxscales->close_maxscale_connections(0);
|
|
Test->check_maxscale_alive(0);
|
|
int rval = Test->global_result;
|
|
delete Test;
|
|
return rval;
|
|
}
|