From d0a28c7ef7ecf50012ebea170d6f9171712ce78a Mon Sep 17 00:00:00 2001 From: yaowei Date: Wed, 8 Jul 2015 19:20:14 +0800 Subject: [PATCH 1/3] fix bug: write sql after SQL_CALC_FOUND_ROWS will corectlly send to master --- bootstrap.sh | 2 +- plugins/proxy/proxy-plugin.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index b4d39e5..8938c7a 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,4 +1,4 @@ #!/bin/sh base=$(cd "$(dirname "$0")"; pwd) cd $base -PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --with-mysql=/usr --prefix=/usr/local/mysql-proxy CFLAGS="-DHAVE_LUA_H -g -O2" LDFLAGS="-lm -ldl -lcrypto -ljemalloc" LUA_CFLAGS="-I/usr/local/include/" LUA_LIBS="-L/usr/local/lib -llua" +PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --with-mysql=/usr --prefix=/usr/local/mysql-proxy CFLAGS="-DHAVE_LUA_H -O2" LDFLAGS="-lm -ldl -lcrypto -ljemalloc" LUA_CFLAGS="-I/usr/local/include/" LUA_LIBS="-L/usr/local/lib -llua" diff --git a/plugins/proxy/proxy-plugin.c b/plugins/proxy/proxy-plugin.c index 53c5bd7..7b1009d 100644 --- a/plugins/proxy/proxy-plugin.c +++ b/plugins/proxy/proxy-plugin.c @@ -1438,6 +1438,13 @@ NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query) { g_ptr_array_free(sqls, TRUE); } + /* the sql after SQL_CALC_FOUND_ROWS must be "select FOUND_ROWS();" + * if not, must redo the read write split operation. because the write sql + * may send to slave. + */ + if (con->is_in_select_calc_found_rows && is_write) { + network_connection_pool_lua_add_connection(con); + } check_flags(tokens, con); From de48e781333a700f2704ed61e60e5eefa8f0edf3 Mon Sep 17 00:00:00 2001 From: winkyao <82091309@qq.com> Date: Tue, 29 Sep 2015 10:39:48 +0800 Subject: [PATCH 2/3] 1. fix bug: when user use 'set autocommit = 0' and after that, user never send any 'commit' statement, the is_in_transaction variable will be true always, which will make all continue sql send to the master, 2. send set statement and show statement to master --- bootstrap.sh | 1 + plugins/proxy/proxy-plugin.c | 39 ++++++++++++++++++++---------------- src/network-mysqld.h | 10 ++++----- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 8938c7a..e25f0aa 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,4 +1,5 @@ #!/bin/sh base=$(cd "$(dirname "$0")"; pwd) cd $base +export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --with-mysql=/usr --prefix=/usr/local/mysql-proxy CFLAGS="-DHAVE_LUA_H -O2" LDFLAGS="-lm -ldl -lcrypto -ljemalloc" LUA_CFLAGS="-I/usr/local/include/" LUA_LIBS="-L/usr/local/lib -llua" diff --git a/plugins/proxy/proxy-plugin.c b/plugins/proxy/proxy-plugin.c index 7b1009d..6671d49 100644 --- a/plugins/proxy/proxy-plugin.c +++ b/plugins/proxy/proxy-plugin.c @@ -1233,6 +1233,7 @@ void modify_charset(GPtrArray* tokens, network_mysqld_con* con) { void check_flags(GPtrArray* tokens, network_mysqld_con* con) { con->is_in_select_calc_found_rows = FALSE; + *is_set_autocommit = FALSE; sql_token** ts = (sql_token**)(tokens->pdata); guint len = tokens->len; @@ -1243,15 +1244,15 @@ void check_flags(GPtrArray* tokens, network_mysqld_con* con) { if (!g_hash_table_lookup(con->locks, key)) g_hash_table_add(con->locks, g_strdup(key)); } - if (len > 4) { //SET AUTOCOMMIT = {0 | 1} - if (ts[1]->token_id == TK_SQL_SET && ts[3]->token_id == TK_EQ) { - if (strcasecmp(ts[2]->text->str, "AUTOCOMMIT") == 0) { - char* str = ts[4]->text->str; - if (strcmp(str, "0") == 0) con->is_not_autocommit = TRUE; - else if (strcmp(str, "1") == 0) con->is_not_autocommit = FALSE; - } - } - } + /* if (len > 4) { //SET AUTOCOMMIT = {0 | 1} */ + /* if (ts[1]->token_id == TK_SQL_SET && ts[3]->token_id == TK_EQ) { */ + /* if (strcasecmp(ts[2]->text->str, "AUTOCOMMIT") == 0) { */ + /* /1* char* str = ts[4]->text->str; *1/ */ + /* /1* if (strcmp(str, "0") == 0) con->is_not_autocommit = TRUE; *1/ */ + /* /1* else if (strcmp(str, "1") == 0) con->is_not_autocommit = FALSE; *1/ */ + /* } */ + /* } */ + /* } */ } guint i; @@ -1302,7 +1303,8 @@ gboolean sql_is_write(GPtrArray *tokens) { token_id = ts[i]->token_id; } - return (token_id != TK_SQL_SELECT && token_id != TK_SQL_SET && token_id != TK_SQL_USE && token_id != TK_SQL_SHOW && token_id != TK_SQL_DESC && token_id != TK_SQL_EXPLAIN); + // "set autocommit = 0; or show variables" need send to master + return (token_id != TK_SQL_SELECT /*&& token_id != TK_SQL_SET */ && token_id != TK_SQL_USE /*&& token_id != TK_SQL_SHOW*/ && token_id != TK_SQL_DESC && token_id != TK_SQL_EXPLAIN); } return TRUE; @@ -1445,7 +1447,7 @@ NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query) { if (con->is_in_select_calc_found_rows && is_write) { network_connection_pool_lua_add_connection(con); } - + check_flags(tokens, con); if (con->server == NULL) { @@ -1453,7 +1455,7 @@ NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query) { if (!con->is_in_transaction && !con->is_not_autocommit && g_hash_table_size(con->locks) == 0) { if (type == COM_QUERY) { - if (is_write) { + if (is_write || is_set_autocommit) { backend_ndx = idle_rw(con); } else { backend_ndx = rw_split(tokens, con); @@ -1819,6 +1821,9 @@ NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query_result) { inj->qstat.server_status = com_query->server_status; inj->qstat.warning_count = com_query->warning_count; inj->qstat.query_status = com_query->query_status; + + con->is_in_transaction = com_query->server_status & SERVER_STATUS_IN_TRANS; + con->is_not_autocommit = !(com_query->server_status & SERVER_STATUS_AUTOCOMMIT); } inj->ts_read_query_result_last = chassis_get_rel_microseconds(); /* g_get_current_time(&(inj->ts_read_query_result_last)); */ @@ -1906,11 +1911,11 @@ NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query_result) { switch (ret) { case PROXY_SEND_RESULT: - if (!con->is_in_transaction || (inj->qstat.server_status & SERVER_STATUS_IN_TRANS)) { - con->is_in_transaction = (inj->qstat.server_status & SERVER_STATUS_IN_TRANS); - } else { - if (strcasestr(str, "COMMIT") == str || strcasestr(str, "ROLLBACK") == str) con->is_in_transaction = FALSE; - } + /* if (!con->is_in_transaction || (inj->qstat.server_status & SERVER_STATUS_IN_TRANS)) { */ + /* con->is_in_transaction = (inj->qstat.server_status & SERVER_STATUS_IN_TRANS); */ + /* } else { */ + /* if (strcasestr(str, "COMMIT") == str || strcasestr(str, "ROLLBACK") == str) con->is_in_transaction = FALSE; */ + /* } */ if (g_hash_table_size(con->locks) > 0 && strcasestr(str, "SELECT RELEASE_LOCK") == str) { gchar* b = strchr(str+strlen("SELECT RELEASE_LOCK"), '(') + 1; diff --git a/src/network-mysqld.h b/src/network-mysqld.h index eee88ad..552fc80 100644 --- a/src/network-mysqld.h +++ b/src/network-mysqld.h @@ -60,12 +60,12 @@ typedef struct network_mysqld_con network_mysqld_con; /* forward declaration */ -#undef NETWORK_MYSQLD_WANT_CON_TRACK_TIME -#ifdef NETWORK_MYSQLD_WANT_CON_TRACK_TIME -#define NETWORK_MYSQLD_CON_TRACK_TIME(con, name) chassis_timestamps_add(con->timestamps, name, __FILE__, __LINE__) -#else +/* #undef NETWORK_MYSQLD_WANT_CON_TRACK_TIME */ +/* #ifdef NETWORK_MYSQLD_WANT_CON_TRACK_TIME */ +/* #define NETWORK_MYSQLD_CON_TRACK_TIME(con, name) chassis_timestamps_add(con->timestamps, name, __FILE__, __LINE__) */ +/* #else */ #define NETWORK_MYSQLD_CON_TRACK_TIME(con, name) -#endif +/* #endif */ /** * A macro that produces a plugin callback function pointer declaration. From 128b0544cefc800366f70e534c5130f35574721c Mon Sep 17 00:00:00 2001 From: winkyao <82091309@qq.com> Date: Tue, 29 Sep 2015 10:46:31 +0800 Subject: [PATCH 3/3] add 'set autocommit = OFF' support --- plugins/proxy/proxy-plugin.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/proxy/proxy-plugin.c b/plugins/proxy/proxy-plugin.c index 6671d49..c9b20ca 100644 --- a/plugins/proxy/proxy-plugin.c +++ b/plugins/proxy/proxy-plugin.c @@ -1233,7 +1233,6 @@ void modify_charset(GPtrArray* tokens, network_mysqld_con* con) { void check_flags(GPtrArray* tokens, network_mysqld_con* con) { con->is_in_select_calc_found_rows = FALSE; - *is_set_autocommit = FALSE; sql_token** ts = (sql_token**)(tokens->pdata); guint len = tokens->len; @@ -1455,7 +1454,7 @@ NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query) { if (!con->is_in_transaction && !con->is_not_autocommit && g_hash_table_size(con->locks) == 0) { if (type == COM_QUERY) { - if (is_write || is_set_autocommit) { + if (is_write ) { backend_ndx = idle_rw(con); } else { backend_ndx = rw_split(tokens, con);