diff options
98 files changed, 3462 insertions, 832 deletions
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index de3cb4890a9..5154f64b98f 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -139,7 +139,7 @@ else # C warnings c_warnings="$warnings" # C++ warnings - cxx_warnings="$warnings -Wno-unused-parameter" + cxx_warnings="$warnings -Wno-unused-parameter -Wno-invalid-offsetof" # cxx_warnings="$cxx_warnings -Woverloaded-virtual -Wsign-promo" cxx_warnings="$cxx_warnings -Wnon-virtual-dtor" debug_extra_cflags="-O0 -g3 -gdwarf-2" diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index c36c8a16881..52474596dfe 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -23,7 +23,7 @@ #include <mysql.h> #include <sql_common.h> -#define ADMIN_VERSION "9.0" +#define ADMIN_VERSION "9.1" #define MAX_MYSQL_VAR 512 #define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */ #define MAX_TRUNC_LENGTH 3 @@ -97,6 +97,7 @@ enum commands { ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD, ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS, ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE, + ADMIN_START_ALL_SLAVES, ADMIN_STOP_ALL_SLAVES, ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_SLOW_LOG, ADMIN_FLUSH_TABLE_STATISTICS, ADMIN_FLUSH_INDEX_STATISTICS, ADMIN_FLUSH_USER_STATISTICS, ADMIN_FLUSH_CLIENT_STATISTICS, @@ -110,6 +111,7 @@ static const char *command_names[]= { "flush-hosts", "flush-tables", "password", "ping", "extended-status", "flush-status", "flush-privileges", "start-slave", "stop-slave", + "start-all-slaves", "stop-all-slaves", "flush-threads", "old-password", "flush-slow-log", "flush-table-statistics", "flush-index-statistics", "flush-user-statistics", "flush-client-statistics", @@ -1113,26 +1115,67 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) } case ADMIN_START_SLAVE: - if (mysql_query(mysql, "START SLAVE")) + case ADMIN_START_ALL_SLAVES: + { + my_bool many_slaves= 0; + const char *query= "START SLAVE"; + if (command == ADMIN_START_ALL_SLAVES && mariadb_connection(mysql) && + mysql_get_server_version(mysql) >= 100000) + { + query="START ALL SLAVES"; + many_slaves= 1; + } + + if (mysql_query(mysql, query)) { my_printf_error(0, "Error starting slave: %s", error_flags, mysql_error(mysql)); return -1; } + else if (!many_slaves || mysql_warning_count(mysql) > 0) + { + if (!option_silent) + puts("Slave('s) started"); + } else - puts("Slave started"); + { + if (!option_silent) + puts("No slaves to start"); + } break; + } case ADMIN_STOP_SLAVE: - if (mysql_query(mysql, "STOP SLAVE")) + case ADMIN_STOP_ALL_SLAVES: + { + const char *query= "STOP SLAVE"; + my_bool many_slaves= 0; + + if (command == ADMIN_STOP_ALL_SLAVES && mariadb_connection(mysql) && + mysql_get_server_version(mysql) >= 100000) + { + query="STOP ALL SLAVES"; + many_slaves= 1; + } + + if (mysql_query(mysql, query)) { my_printf_error(0, "Error stopping slave: %s", error_flags, mysql_error(mysql)); return -1; } + else if (!many_slaves || mysql_warning_count(mysql) > 0) + { + /* We can't detect if there was any slaves to stop with STOP SLAVE */ + if (many_slaves && !option_silent) + puts("Slave('s) stopped"); + } else - puts("Slave stopped"); + { + if (!option_silent) + puts("All slaves was already stopped"); + } break; - + } case ADMIN_PING: mysql->reconnect=0; /* We want to know of reconnects */ if (!mysql_ping(mysql)) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index bb89db4b231..f824d53ed1b 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -253,6 +253,8 @@ static void init_re(void); static int match_re(my_regex_t *, char *); static void free_re(void); +static char *get_string(char **to_ptr, char **from_ptr, + struct st_command *command); static int replace(DYNAMIC_STRING *ds_str, const char *search_str, ulong search_len, const char *replace_str, ulong replace_len); @@ -4580,7 +4582,8 @@ void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused))) } -void do_sync_with_master2(struct st_command *command, long offset) +void do_sync_with_master2(struct st_command *command, long offset, + const char *connection_name) { MYSQL_RES *res; MYSQL_ROW row; @@ -4591,8 +4594,9 @@ void do_sync_with_master2(struct st_command *command, long offset) if (!master_pos.file[0]) die("Calling 'sync_with_master' without calling 'save_master_pos'"); - sprintf(query_buf, "select master_pos_wait('%s', %ld, %d)", - master_pos.file, master_pos.pos + offset, timeout); + sprintf(query_buf, "select master_pos_wait('%s', %ld, %d, '%s')", + master_pos.file, master_pos.pos + offset, timeout, + connection_name); if (mysql_query(mysql, query_buf)) die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql), @@ -4652,16 +4656,32 @@ void do_sync_with_master(struct st_command *command) long offset= 0; char *p= command->first_argument; const char *offset_start= p; + char *start, *buff= 0; + start= (char*) ""; + if (*offset_start) { for (; my_isdigit(charset_info, *p); p++) offset = offset * 10 + *p - '0'; - if(*p && !my_isspace(charset_info, *p)) + if (*p && !my_isspace(charset_info, *p) && *p != ',') die("Invalid integer argument \"%s\"", offset_start); + + while (*p && my_isspace(charset_info, *p)) + p++; + if (*p == ',') + { + p++; + while (*p && my_isspace(charset_info, *p)) + p++; + start= buff= (char*)my_malloc(strlen(p)+1,MYF(MY_WME | MY_FAE)); + get_string(&buff, &p, command); + } command->last_argument= p; } - do_sync_with_master2(command, offset); + do_sync_with_master2(command, offset, start); + if (buff) + my_free(start); return; } @@ -5286,7 +5306,7 @@ void do_get_errcodes(struct st_command *command) { die("The sqlstate definition must start with an uppercase S"); } - else if (*p == 'E') + else if (*p == 'E' || *p == 'W') { /* Error name string */ @@ -5295,9 +5315,9 @@ void do_get_errcodes(struct st_command *command) to->type= ERR_ERRNO; DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum)); } - else if (*p == 'e') + else if (*p == 'e' || *p == 'w') { - die("The error name definition must start with an uppercase E"); + die("The error name definition must start with an uppercase E or W"); } else { @@ -5360,8 +5380,8 @@ void do_get_errcodes(struct st_command *command) If string is a '$variable', return the value of the variable. */ -char *get_string(char **to_ptr, char **from_ptr, - struct st_command *command) +static char *get_string(char **to_ptr, char **from_ptr, + struct st_command *command) { char c, sep; char *to= *to_ptr, *from= *from_ptr, *start=to; @@ -9288,7 +9308,7 @@ int main(int argc, char **argv) select_connection(command); else select_connection_name("slave"); - do_sync_with_master2(command, 0); + do_sync_with_master2(command, 0, ""); break; } case Q_COMMENT: diff --git a/cmake/maintainer.cmake b/cmake/maintainer.cmake index a70226e2b6e..d52405e8bcc 100644 --- a/cmake/maintainer.cmake +++ b/cmake/maintainer.cmake @@ -18,7 +18,7 @@ INCLUDE(CheckCCompilerFlag) # Setup GCC (GNU C compiler) warning options. MACRO(SET_MYSQL_MAINTAINER_GNU_C_OPTIONS) SET(MY_MAINTAINER_WARNINGS - "-Wall -Wextra -Wunused -Wwrite-strings -Wno-strict-aliasing -DFORCE_INIT_OF_VARS") + "-Wall -Wextra -Wunused -Wwrite-strings -Wno-strict-aliasing -Wno-invalid-offsetof -DFORCE_INIT_OF_VARS") CHECK_C_COMPILER_FLAG("-Wno-missing-field-initializers" HAVE_NO_MISSING_FIELD_INITIALIZERS) diff --git a/include/my_sys.h b/include/my_sys.h index 1d666cb4a60..336b5635dd8 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -679,6 +679,7 @@ extern my_bool has_path(const char *name); extern char *convert_dirname(char *to, const char *from, const char *from_end); extern void to_unix_path(char * name); extern char * fn_ext(const char *name); +extern char * fn_ext2(const char *name); extern char * fn_same(char * toname,const char *name,int flag); extern char * fn_format(char * to,const char *name,const char *dir, const char *form, uint flag); diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index b73f2d75193..b8e90f764bd 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -167,7 +167,7 @@ enum enum_mysql_show_type SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, - SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, SHOW_always_last }; diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index b987f690592..dea2446ac9c 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -94,7 +94,7 @@ enum enum_mysql_show_type SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, - SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, SHOW_always_last }; struct st_mysql_show_var { diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index 113aaf62d19..f1213a73bc6 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -94,7 +94,7 @@ enum enum_mysql_show_type SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, - SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, SHOW_always_last }; struct st_mysql_show_var { diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index 6011e7f7519..74b298098dd 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -94,7 +94,7 @@ enum enum_mysql_show_type SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, - SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, SHOW_always_last }; struct st_mysql_show_var { diff --git a/mysql-test/extra/rpl_tests/rpl_max_relay_size.test b/mysql-test/extra/rpl_tests/rpl_max_relay_size.test index d8cd4f2d284..0fcff5ebe6c 100644 --- a/mysql-test/extra/rpl_tests/rpl_max_relay_size.test +++ b/mysql-test/extra/rpl_tests/rpl_max_relay_size.test @@ -34,7 +34,7 @@ reset slave; --echo # Test 1 --echo # -set @my_max_binlog_size= @@global.max_binlog_size; +set @my_max_binlog_size= @@global.max_binlog_size, @my_max_relay_log_size=@@global.max_relay_log_size; set global max_binlog_size=8192; set global max_relay_log_size=8192-1; # mapped to 4096 select @@global.max_relay_log_size; @@ -110,6 +110,7 @@ source include/show_master_status.inc; # Restore max_binlog_size connection slave; set global max_binlog_size= @my_max_binlog_size; +set global max_relay_log_size= @my_max_relay_log_size; --echo # --echo # End of 4.1 tests diff --git a/mysql-test/include/setup_fake_relay_log.inc b/mysql-test/include/setup_fake_relay_log.inc index 4f1d4f6f162..a1964572427 100644 --- a/mysql-test/include/setup_fake_relay_log.inc +++ b/mysql-test/include/setup_fake_relay_log.inc @@ -74,7 +74,6 @@ let $_fake_relay_index= $_fake_datadir/$_fake_filename.index; let $_fake_relay_log_purge= `SELECT @@global.relay_log_purge`; RESET SLAVE; -let $_orphan_relay_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1); # Create relay log file. --copy_file $fake_relay_log $_fake_relay_log @@ -103,8 +102,5 @@ let $_orphan_relay_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1); # Setup replication from existing relay log. eval CHANGE MASTER TO MASTER_HOST='dummy.localdomain', RELAY_LOG_FILE='$_fake_filename-fake.000001', RELAY_LOG_POS=4; -# remove the orphan log file (became spurious) --- remove_file $_fake_datadir/$_orphan_relay_file - --let $include_filename= setup_fake_relay_log.inc --source include/end_include_file.inc diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 8c4013e1c24..768016d94aa 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -174,6 +174,7 @@ my $DEFAULT_SUITES= join(',', map { "$_-" } qw( heap innodb maria + multi_source optimizer_unfixed_bugs oqgraph parts diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result index d3b3cd16210..b64351045bf 100644 --- a/mysql-test/r/flush.result +++ b/mysql-test/r/flush.result @@ -489,3 +489,10 @@ UNLOCK TABLES; # Switching to connection 'default'. COMMIT; DROP TABLE t1; +# +# Test flushing slave or relay logs twice +# +flush relay logs,relay logs; +ERROR HY000: Incorrect usage of FLUSH and RELAY LOGS +flush slave,slave; +ERROR HY000: Incorrect usage of FLUSH and SLAVE diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 718909d1b27..628d38a8523 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -357,8 +357,7 @@ The following options may be given as the first argument: --max-binlog-cache-size=# Sets the total size of the transactional cache --max-binlog-size=# Binary log will be rotated automatically when the size - exceeds this value. Will also apply to relay logs if - max_relay_log_size is 0 + exceeds this value. --max-binlog-stmt-cache-size=# Sets the total size of the statement cache --max-connect-errors=# @@ -384,9 +383,9 @@ The following options may be given as the first argument: --max-prepared-stmt-count=# Maximum number of prepared statements in the server --max-relay-log-size=# - If non-zero: relay log will be rotated automatically when - the size exceeds this value; if zero: when the size - exceeds max_binlog_size + relay log will be rotated automatically when the size + exceeds this value. If 0 are startup, it's set to + max_binlog_size --max-seeks-for-key=# Limit assumed max number of seeks when looking up rows based on a key @@ -741,7 +740,7 @@ The following options may be given as the first argument: The maximum packet length to sent successfully from the master to slave. --slave-net-timeout=# - Number of seconds to wait for more data from a + Number of seconds to wait for more data from any master/slave connection before aborting the read --slave-skip-errors=name Tells the slave thread to continue replication when a @@ -965,7 +964,7 @@ max-join-size 18446744073709551615 max-length-for-sort-data 1024 max-long-data-size 1048576 max-prepared-stmt-count 16382 -max-relay-log-size 0 +max-relay-log-size 1073741824 max-seeks-for-key 18446744073709551615 max-sort-length 1024 max-sp-recursion-depth 0 diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index fdb3029059f..d08ffd96a04 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -232,7 +232,7 @@ mysqltest: At line 2: Spurious text after `query` expression mysqltest: At line 1: Missing argument(s) to 'error' mysqltest: At line 1: Missing argument(s) to 'error' mysqltest: At line 1: The sqlstate definition must start with an uppercase S -mysqltest: At line 1: The error name definition must start with an uppercase E +mysqltest: At line 1: The error name definition must start with an uppercase E or W mysqltest: At line 1: Invalid argument to error: '9eeeee' - the errno may only consist of digits[0-9] mysqltest: At line 1: Invalid argument to error: '1sssss' - the errno may only consist of digits[0-9] mysqltest: At line 1: The sqlstate must be exactly 5 chars long diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 10700d0ba73..54378f16d49 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -441,7 +441,7 @@ select master_pos_wait(); ERROR 42000: Incorrect parameter count in the call to native function 'master_pos_wait' select master_pos_wait(1); ERROR 42000: Incorrect parameter count in the call to native function 'master_pos_wait' -select master_pos_wait(1, 2, 3, 4); +select master_pos_wait(1, 2, 3, 4, 5); ERROR 42000: Incorrect parameter count in the call to native function 'master_pos_wait' select rand(1, 2, 3); ERROR 42000: Incorrect parameter count in the call to native function 'rand' diff --git a/mysql-test/r/signal_code.result b/mysql-test/r/signal_code.result index ca46f1d2079..4cd1de97729 100644 --- a/mysql-test/r/signal_code.result +++ b/mysql-test/r/signal_code.result @@ -20,16 +20,16 @@ return 0; end $$ show procedure code signal_proc; Pos Instruction -0 stmt 130 "SIGNAL foo" -1 stmt 130 "SIGNAL foo SET MESSAGE_TEXT = "This i..." -2 stmt 131 "RESIGNAL foo" -3 stmt 131 "RESIGNAL foo SET MESSAGE_TEXT = "This..." +0 stmt 132 "SIGNAL foo" +1 stmt 132 "SIGNAL foo SET MESSAGE_TEXT = "This i..." +2 stmt 133 "RESIGNAL foo" +3 stmt 133 "RESIGNAL foo SET MESSAGE_TEXT = "This..." drop procedure signal_proc; show function code signal_func; Pos Instruction -0 stmt 130 "SIGNAL foo" -1 stmt 130 "SIGNAL foo SET MESSAGE_TEXT = "This i..." -2 stmt 131 "RESIGNAL foo" -3 stmt 131 "RESIGNAL foo SET MESSAGE_TEXT = "This..." +0 stmt 132 "SIGNAL foo" +1 stmt 132 "SIGNAL foo SET MESSAGE_TEXT = "This i..." +2 stmt 133 "RESIGNAL foo" +3 stmt 133 "RESIGNAL foo SET MESSAGE_TEXT = "This..." 4 freturn 3 0 drop function signal_func; diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index 67651294498..3061c58747a 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -155,11 +155,11 @@ Pos Instruction 0 stmt 9 "drop temporary table if exists sudoku..." 1 stmt 1 "create temporary table sudoku_work ( ..." 2 stmt 1 "create temporary table sudoku_schedul..." -3 stmt 88 "call sudoku_init()" +3 stmt 90 "call sudoku_init()" 4 jump_if_not 7(8) p_naive@0 5 stmt 4 "update sudoku_work set cnt = 0 where ..." 6 jump 8 -7 stmt 88 "call sudoku_count()" +7 stmt 90 "call sudoku_count()" 8 stmt 6 "insert into sudoku_schedule (row,col)..." 9 set v_scounter@2 0 10 set v_i@3 1 diff --git a/mysql-test/suite/multi_source/info_logs-master.opt b/mysql-test/suite/multi_source/info_logs-master.opt new file mode 100644 index 00000000000..da4e6d3c455 --- /dev/null +++ b/mysql-test/suite/multi_source/info_logs-master.opt @@ -0,0 +1 @@ +--relay-log=relay.bin --relay-log-info=relay.bin.info diff --git a/mysql-test/suite/multi_source/info_logs.result b/mysql-test/suite/multi_source/info_logs.result new file mode 100644 index 00000000000..f192cf17fbb --- /dev/null +++ b/mysql-test/suite/multi_source/info_logs.result @@ -0,0 +1,115 @@ +# +# List of files matching '*info*' pattern before starting any slaves +multi-master.info +# End of list +# +# Contents of multi-master.info +# EOF +# +change master 'master1' to +master_port=MYPORT_1, +master_host='127.0.0.1', +master_user='root'; +start slave 'master1'; +set default_master_connection = 'master1'; +include/wait_for_slave_to_start.inc +# +# List of files matching '*info*' pattern while 'master1' is running +master-master1.info +multi-master.info +relay.bin-master1.info +# End of list +# +# Contents of multi-master.info +master1 +# EOF +# +change master 'MASTER 2.2' to +master_port=MYPORT_2, +master_host='127.0.0.1', +master_user='root'; +start slave 'MASTER 2.2'; +set default_master_connection = 'MASTER 2.2'; +include/wait_for_slave_to_start.inc +# +# List of files matching '*info*' pattern +# while 'master1' and 'MASTER 2.2' are running +master-master1.info +master-master@00202@002e2.info +multi-master.info +relay.bin-master1.info +relay.bin-master@00202@002e2.info +# End of list +# +# Contents of multi-master.info +master1 +MASTER 2.2 +# EOF +# +stop slave 'master1'; +set default_master_connection = 'master1'; +include/wait_for_slave_to_stop.inc +reset slave 'master1' all; +# +# List of files matching '*info*' pattern +# after 'master1' was completely reset, 'MASTER 2.2' still running +master-master@00202@002e2.info +multi-master.info +relay.bin-master@00202@002e2.info +# End of list +# +# Contents of multi-master.info +MASTER 2.2 +# EOF +# +set default_master_connection = ''; +change master to +master_port=MYPORT_1, +master_host='127.0.0.1', +master_user='root'; +start slave; +include/wait_for_slave_to_start.inc +# +# List of files matching '*info*' pattern +# while 'MASTER 2.2' and '' are running +master-master@00202@002e2.info +master.info +multi-master.info +relay.bin-master@00202@002e2.info +relay.bin.info +# End of list +# +# Contents of multi-master.info +MASTER 2.2 +# EOF +# +show all slaves status; +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 286 relay.000002 572 master-bin.000001 Yes Yes 0 0 286 857 None 0 No 0 No 0 0 1 0 1073741824 6 0 60.000 +MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 286 relay-master@00202@002e2.000002 572 master-bin.000001 Yes Yes 0 0 286 876 None 0 No 0 No 0 0 2 0 1073741824 6 0 60.000 +show all slaves status; +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 286 relay.000004 532 master-bin.000001 Yes Yes 0 0 286 817 None 0 No 0 No 0 0 1 0 1073741824 6 0 60.000 +MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 286 relay-master@00202@002e2.000004 532 master-bin.000001 Yes Yes 0 0 286 836 None 0 No 0 No 0 0 2 0 1073741824 6 0 60.000 +# +# List of files matching '*info*' pattern +# after slave server restart +# while 'MASTER 2.2' and '' are running +master-master@00202@002e2.info +master.info +multi-master.info +relay.bin-master@00202@002e2.info +relay.bin.info +# End of list +# +# Contents of multi-master.info +MASTER 2.2 +# EOF +# +stop slave; +include/wait_for_slave_to_stop.inc +set default_master_connection = 'MASTER 2.2'; +stop slave; +include/wait_for_slave_to_stop.inc +reset slave all; +reset slave '' all; diff --git a/mysql-test/suite/multi_source/info_logs.test b/mysql-test/suite/multi_source/info_logs.test new file mode 100644 index 00000000000..6314a94434c --- /dev/null +++ b/mysql-test/suite/multi_source/info_logs.test @@ -0,0 +1,160 @@ +# +# Check log files with multi-source +# + +--connect (slave,127.0.0.1,root,,,$SERVER_MYPORT_3) + +--let $datadir = `SELECT @@datadir` + +# +# Check creation and updating of multi-source *info* logs +# + +--echo # +--echo # List of files matching '*info*' pattern before starting any slaves +--list_files $datadir *info* +--echo # End of list +--echo # +--echo # Contents of multi-master.info +--cat_file $datadir/multi-master.info +--echo # EOF +--echo # + +# Start replication from the first master + +--replace_result $SERVER_MYPORT_1 MYPORT_1 +eval change master 'master1' to +master_port=$SERVER_MYPORT_1, +master_host='127.0.0.1', +master_user='root'; + +start slave 'master1'; +set default_master_connection = 'master1'; +--source include/wait_for_slave_to_start.inc + +# Check the files + +--echo # +--echo # List of files matching '*info*' pattern while 'master1' is running +--list_files $datadir *info* +--echo # End of list +--echo # +--echo # Contents of multi-master.info +--cat_file $datadir/multi-master.info +--echo # EOF +--echo # + +# Start replication from the second master + +--replace_result $SERVER_MYPORT_2 MYPORT_2 +eval change master 'MASTER 2.2' to +master_port=$SERVER_MYPORT_2, +master_host='127.0.0.1', +master_user='root'; + +start slave 'MASTER 2.2'; +set default_master_connection = 'MASTER 2.2'; +--source include/wait_for_slave_to_start.inc + +# Check the files + +--echo # +--echo # List of files matching '*info*' pattern +--echo # while 'master1' and 'MASTER 2.2' are running +--list_files $datadir *info* +--echo # End of list +--echo # +--echo # Contents of multi-master.info +--cat_file $datadir/multi-master.info +--echo # EOF +--echo # + +# Remove master1 configuration + +stop slave 'master1'; +set default_master_connection = 'master1'; +--source include/wait_for_slave_to_stop.inc +reset slave 'master1' all; + +# Check the files + +--echo # +--echo # List of files matching '*info*' pattern +--echo # after 'master1' was completely reset, 'MASTER 2.2' still running +--list_files $datadir *info* +--echo # End of list +--echo # +--echo # Contents of multi-master.info +--cat_file $datadir/multi-master.info +--echo # EOF +--echo # + +# Start replication from the first master, +# now with the default empty name + +set default_master_connection = ''; +--replace_result $SERVER_MYPORT_1 MYPORT_1 +eval change master to +master_port=$SERVER_MYPORT_1, +master_host='127.0.0.1', +master_user='root'; + +start slave; +--source include/wait_for_slave_to_start.inc + +# Check the files + +--echo # +--echo # List of files matching '*info*' pattern +--echo # while 'MASTER 2.2' and '' are running +--list_files $datadir *info* +--echo # End of list +--echo # +--echo # Contents of multi-master.info +--cat_file $datadir/multi-master.info +--echo # EOF +--echo # + +--sleep 5 +--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 +show all slaves status; + +# Restart the slave server + +--enable_reconnect +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect +restart +EOF +--shutdown_server 60 +--source include/wait_until_connected_again.inc + +--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 +show all slaves status; + +# Check the files + +--echo # +--echo # List of files matching '*info*' pattern +--echo # after slave server restart +--echo # while 'MASTER 2.2' and '' are running +--list_files $datadir *info* +--echo # End of list +--echo # +--echo # Contents of multi-master.info +--cat_file $datadir/multi-master.info +--echo # EOF +--echo # + + +# Cleanup + +stop slave; +--source include/wait_for_slave_to_stop.inc + +set default_master_connection = 'MASTER 2.2'; +stop slave; +--source include/wait_for_slave_to_stop.inc +reset slave all; +reset slave '' all; + +--disconnect slave diff --git a/mysql-test/suite/multi_source/my.cnf b/mysql-test/suite/multi_source/my.cnf new file mode 100644 index 00000000000..826967b52f9 --- /dev/null +++ b/mysql-test/suite/multi_source/my.cnf @@ -0,0 +1,25 @@ +# cat t/multisource1.cnf +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] +server-id=1 +log-bin=master-bin +log-warnings=2 + +[mysqld.2] +server-id=2 +log-bin=master-bin +log-warnings=2 + +[mysqld.3] +server-id=3 +log-warnings=2 + +[ENV] +SERVER_MYPORT_1= @mysqld.1.port +SERVER_MYSOCK_1= @mysqld.1.socket +SERVER_MYPORT_2= @mysqld.2.port +SERVER_MYSOCK_2= @mysqld.2.socket +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/multi_source/relaylog_events.result b/mysql-test/suite/multi_source/relaylog_events.result new file mode 100644 index 00000000000..437dc87788a --- /dev/null +++ b/mysql-test/suite/multi_source/relaylog_events.result @@ -0,0 +1,29 @@ +change master 'master1' to +master_port=MYPORT_1, +master_host='127.0.0.1', +master_user='root'; +start slave 'master1'; +set default_master_connection = 'master1'; +include/wait_for_slave_to_start.inc +drop table if exists t1; +create table t1 (i int) engine=MyISAM; +mysqld-relay-bin-master1.000001 +mysqld-relay-bin-master1.000002 +mysqld-relay-bin-master1.index +show relaylog events in 'mysqld-relay-bin-master1.000002'; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-relay-bin-master1.000002 4 Format_desc 3 246 Server version +mysqld-relay-bin-master1.000002 246 Rotate 1 0 master-bin.000001;pos=4 +mysqld-relay-bin-master1.000002 290 Format_desc 1 246 Server version +mysqld-relay-bin-master1.000002 532 Binlog_checkpoint 1 286 master-bin.000001 +mysqld-relay-bin-master1.000002 572 Query 1 400 use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */ +mysqld-relay-bin-master1.000002 686 Query 1 500 use `test`; create table t1 (i int) engine=MyISAM +show relaylog events; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-relay-bin-master1.000001 4 Format_desc 3 246 Server version +mysqld-relay-bin-master1.000001 246 Rotate 3 304 mysqld-relay-bin-master1.000002;pos=4 +drop table t1; +stop slave; +include/wait_for_slave_to_stop.inc +reset slave 'master1' all; +reset master; diff --git a/mysql-test/suite/multi_source/relaylog_events.test b/mysql-test/suite/multi_source/relaylog_events.test new file mode 100644 index 00000000000..b5bbf726316 --- /dev/null +++ b/mysql-test/suite/multi_source/relaylog_events.test @@ -0,0 +1,52 @@ +# +# Check that SHOW RELAYLOG EVENTS can be used +# for a named master connection +# + +--connect (slave,127.0.0.1,root,,,$SERVER_MYPORT_3) + +--replace_result $SERVER_MYPORT_1 MYPORT_1 +eval change master 'master1' to +master_port=$SERVER_MYPORT_1, +master_host='127.0.0.1', +master_user='root'; + +start slave 'master1'; +set default_master_connection = 'master1'; +--source include/wait_for_slave_to_start.inc + +--connect (master1,127.0.0.1,root,,,$SERVER_MYPORT_1) +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (i int) engine=MyISAM; +--save_master_pos + +--connection slave +--sync_with_master 0,'master1' + +--let $datadir = `SELECT @@datadir` +--list_files $datadir mysqld-relay-bin-master1.* + +--replace_regex /Server ver:.*/Server version/ +show relaylog events in 'mysqld-relay-bin-master1.000002'; +--replace_regex /Server ver:.*/Server version/ +show relaylog events; + +--connection master1 +drop table t1; +--save_master_pos + +--connection slave +--sync_with_master 0,'master1' +stop slave; +--source include/wait_for_slave_to_stop.inc + +reset slave 'master1' all; + +--disconnect slave + +--connection master1 +reset master; +--disconnect master1 + diff --git a/mysql-test/suite/multi_source/reset_slave.result b/mysql-test/suite/multi_source/reset_slave.result new file mode 100644 index 00000000000..ab59f54315a --- /dev/null +++ b/mysql-test/suite/multi_source/reset_slave.result @@ -0,0 +1,27 @@ +change master 'master1' to +master_port=MYPORT_1, +master_host='127.0.0.1', +master_user='root'; +start slave 'master1'; +set default_master_connection = 'master1'; +include/wait_for_slave_to_start.inc +drop table if exists t1; +create table t1 (i int) engine=MyISAM; +insert into t1 values (1),(2); +stop slave 'master1'; +show slave 'master1' status; +Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id + 127.0.0.1 root MYPORT_1 60 master-bin.000001 729 mysqld-relay-bin-master1.000002 1015 master-bin.000001 No No 0 0 729 1319 None 0 No NULL No 0 0 1 +mysqld-relay-bin-master1.000001 +mysqld-relay-bin-master1.000002 +mysqld-relay-bin-master1.index +reset slave 'master1'; +show slave 'master1' status; +Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id + 127.0.0.1 root MYPORT_1 60 4 1015 No No 0 0 0 1319 None 0 No NULL No 0 0 1 +reset slave 'master1' all; +show slave 'master1' status; +ERROR HY000: There is no master connection 'master1' +drop table t1; +drop table t1; +reset master; diff --git a/mysql-test/suite/multi_source/reset_slave.test b/mysql-test/suite/multi_source/reset_slave.test new file mode 100644 index 00000000000..d3b9abb91ca --- /dev/null +++ b/mysql-test/suite/multi_source/reset_slave.test @@ -0,0 +1,62 @@ +#--enable_connect_log +--connect (slave,127.0.0.1,root,,,$SERVER_MYPORT_3) + +--replace_result $SERVER_MYPORT_1 MYPORT_1 +eval change master 'master1' to +master_port=$SERVER_MYPORT_1, +master_host='127.0.0.1', +master_user='root'; + +start slave 'master1'; + +set default_master_connection = 'master1'; +--source include/wait_for_slave_to_start.inc + +--connect (master1,127.0.0.1,root,,,$SERVER_MYPORT_1) + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1 (i int) engine=MyISAM; +insert into t1 values (1),(2); + +--save_master_pos + +--connection slave + +--sync_with_master 0,'master1' +stop slave 'master1'; + +--wait_for_slave_to_stop + +--let $datadir = `SELECT @@datadir` + +--replace_result $SERVER_MYPORT_1 MYPORT_1 +show slave 'master1' status; +--list_files $datadir mysqld* + +reset slave 'master1'; + +--replace_result $SERVER_MYPORT_1 MYPORT_1 +show slave 'master1' status; +--list_files $datadir mysqld* + +reset slave 'master1' all; + +--error WARN_NO_MASTER_INFO +show slave 'master1' status; +--list_files $datadir mysqld* + +# Cleanup + +drop table t1; +--disconnect slave + +--connection master1 +drop table t1; +reset master; +--disconnect master1 + + + diff --git a/mysql-test/suite/multi_source/simple.result b/mysql-test/suite/multi_source/simple.result new file mode 100644 index 00000000000..8465c4a5c52 --- /dev/null +++ b/mysql-test/suite/multi_source/simple.result @@ -0,0 +1,75 @@ +change master 'slave1' to master_port=MYPORT_1, master_host='127.0.0.1', master_user='root'; +change master 'slave2' to master_port=MYPORT_2, master_host='127.0.0.1', master_user='root'; +start slave 'slave1'; +set default_master_connection = 'slave1'; +include/wait_for_slave_to_start.inc +set default_master_connection = 'slave2'; +start all slaves; +Warnings: +Note 1936 SLAVE 'slave2' started +include/wait_for_slave_to_start.inc +set default_master_connection = ''; +show all slaves status; +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period +slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 286 mysqld-relay-bin-slave1.000002 572 master-bin.000001 Yes Yes 0 0 286 875 None 0 No 0 No 0 0 1 0 1073741824 6 0 60.000 +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 286 mysqld-relay-bin-slave2.000002 572 master-bin.000001 Yes Yes 0 0 286 875 None 0 No 0 No 0 0 2 0 1073741824 6 0 60.000 +start all slaves; +stop slave 'slave1'; +show slave 'slave1' status; +Slave_IO_State +Master_Host 127.0.0.1 +Master_User root +Master_Port MYPORT_1 +Connect_Retry 60 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 286 +Relay_Log_File mysqld-relay-bin-slave1.000002 +Relay_Log_Pos 572 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 286 +Relay_Log_Space 875 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master NULL +Master_SSL_Verify_Server_Cert No +Last_IO_Errno 0 +Last_IO_Error +Last_SQL_Errno 0 +Last_SQL_Error +Replicate_Ignore_Server_Ids +Master_Server_Id 1 +reset slave 'slave1'; +show all slaves status; +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period +slave1 127.0.0.1 root MYPORT_1 60 4 572 No No 0 0 0 875 None 0 No NULL No 0 0 1 0 1073741824 6 0 60.000 +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 286 mysqld-relay-bin-slave2.000002 572 master-bin.000001 Yes Yes 0 0 286 875 None 0 No 0 No 0 0 2 0 1073741824 6 0 60.000 +reset slave 'slave1' all; +show all slaves status; +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 286 mysqld-relay-bin-slave2.000002 572 master-bin.000001 Yes Yes 0 0 286 875 None 0 No 0 No 0 0 2 0 1073741824 6 0 60.000 +stop all slaves; +Warnings: +Note 1937 SLAVE 'slave2' stopped +show all slaves status; +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period +slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 286 mysqld-relay-bin-slave2.000002 572 master-bin.000001 No No 0 0 286 875 None 0 No NULL No 0 0 2 0 1073741824 6 0 60.000 +stop all slaves; +reset slave 'slave2' all; diff --git a/mysql-test/suite/multi_source/simple.test b/mysql-test/suite/multi_source/simple.test new file mode 100644 index 00000000000..4b13623785a --- /dev/null +++ b/mysql-test/suite/multi_source/simple.test @@ -0,0 +1,62 @@ +# +# Simple multi-master test +# + +--connect (slave,127.0.0.1,root,,,$SERVER_MYPORT_3) +--connect (master1,127.0.0.1,root,,,$SERVER_MYPORT_1) +--connect (master2,127.0.0.1,root,,,$SERVER_MYPORT_2) +--connection slave + +--replace_result $SERVER_MYPORT_1 MYPORT_1 +eval change master 'slave1' to master_port=$SERVER_MYPORT_1, master_host='127.0.0.1', master_user='root'; +--replace_result $SERVER_MYPORT_2 MYPORT_2 +eval change master 'slave2' to master_port=$SERVER_MYPORT_2, master_host='127.0.0.1', master_user='root'; +start slave 'slave1'; +set default_master_connection = 'slave1'; +--source include/wait_for_slave_to_start.inc +set default_master_connection = 'slave2'; +start all slaves; + +--source include/wait_for_slave_to_start.inc +set default_master_connection = ''; + +# Ensure that all data is in the relay log +--connection master1 +--save_master_pos +--connection slave +--sync_with_master 0,'slave1' +--connection master2 +--save_master_pos +--connection slave +--sync_with_master 0,'slave2' + +--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 +show all slaves status; + +# Ensure that start all slaves doesn't do anything as all slaves are started +start all slaves; + +stop slave 'slave1'; + +--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 +query_vertical show slave 'slave1' status; + +reset slave 'slave1'; +--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 +show all slaves status; + +reset slave 'slave1' all; +--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 +show all slaves status; + +stop all slaves; +--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 +show all slaves status; + +# Ensure that start all slaves doesn't do anything as all slaves are stopped +stop all slaves; + +# +# clean up +# +reset slave 'slave2' all; diff --git a/mysql-test/suite/multi_source/skip_counter.result b/mysql-test/suite/multi_source/skip_counter.result new file mode 100644 index 00000000000..51ad36c4ee8 --- /dev/null +++ b/mysql-test/suite/multi_source/skip_counter.result @@ -0,0 +1,126 @@ +connect master1,127.0.0.1,root,,,$SERVER_MYPORT_1; +drop database if exists db; +create database db; +create table db.t1 (i int) engine=MyISAM; +connect master2,127.0.0.1,root,,,$SERVER_MYPORT_2; +drop database if exists db; +create database db; +create table db.t2 (i int) engine=MyISAM; +connect slave,127.0.0.1,root,,,$SERVER_MYPORT_3; +change master 'master1' to +master_port=MYPORT_1, +master_host='127.0.0.1', +master_user='root'; +start slave 'master1'; +set default_master_connection = 'master1'; +include/wait_for_slave_to_start.inc +set default_master_connection = 'master2'; +change master 'master2' to +master_port=MYPORT_2, +master_host='127.0.0.1', +master_user='root'; +set global sql_slave_skip_counter = 2; +select @@global.sql_slave_skip_counter; +@@global.sql_slave_skip_counter +2 +select @@session.sql_slave_skip_counter; +@@session.sql_slave_skip_counter +2 +set session sql_slave_skip_counter = 3; +select @@global.sql_slave_skip_counter; +@@global.sql_slave_skip_counter +3 +select @@session.sql_slave_skip_counter; +@@session.sql_slave_skip_counter +3 +set global sql_slave_skip_counter= default; +select @@global.sql_slave_skip_counter; +@@global.sql_slave_skip_counter +0 +select @@session.sql_slave_skip_counter; +@@session.sql_slave_skip_counter +0 +set global sql_slave_skip_counter= 3; +set default_master_connection = 'master1'; +select @@session.sql_slave_skip_counter; +@@session.sql_slave_skip_counter +0 +set default_master_connection = 'qqq'; +select @@session.sql_slave_skip_counter; +@@session.sql_slave_skip_counter +0 +Warnings: +Warning 1617 There is no master connection 'qqq' +set default_master_connection = 'master2'; +select @@session.sql_slave_skip_counter; +@@session.sql_slave_skip_counter +3 +select @@global.max_relay_log_size; +@@global.max_relay_log_size +1073741824 +set global max_relay_log_size = 1*1024*1024; +select @@global.max_relay_log_size; +@@global.max_relay_log_size +1048576 +select @@session.max_relay_log_size; +@@session.max_relay_log_size +1048576 +set session max_relay_log_size = 3*1024*1024; +select @@global.max_relay_log_size; +@@global.max_relay_log_size +3145728 +select @@session.max_relay_log_size; +@@session.max_relay_log_size +3145728 +set global max_relay_log_size= default; +select @@global.max_relay_log_size; +@@global.max_relay_log_size +1073741824 +select @@session.max_relay_log_size; +@@session.max_relay_log_size +1073741824 +set global max_relay_log_size= 3*1024*1024; +set default_master_connection = 'master1'; +select @@session.max_relay_log_size; +@@session.max_relay_log_size +1073741824 +set default_master_connection = 'qqq'; +select @@session.max_relay_log_size; +@@session.max_relay_log_size +0 +Warnings: +Warning 1617 There is no master connection 'qqq' +set default_master_connection = 'master2'; +select @@session.max_relay_log_size; +@@session.max_relay_log_size +3145728 +set global max_binlog_size= 4*1024*1024; +select @@global.max_relay_log_size; +@@global.max_relay_log_size +3145728 +start slave 'master2'; +include/wait_for_slave_to_start.inc +set default_master_connection = ''; +connection master2; +connection slave; +show tables in db; +Tables_in_db +t1 +t2 +drop database db; +set default_master_connection = 'master1'; +stop slave; +include/wait_for_slave_to_stop.inc +set default_master_connection = 'master2'; +stop slave; +include/wait_for_slave_to_stop.inc +set global sql_slave_skip_counter = 0; +set global max_relay_log_size = 1073741824; +set global max_binlog_size = 1073741824; +disconnect slave; +connection master1; +drop database db; +disconnect master1; +connection master2; +drop database db; +disconnect master2; diff --git a/mysql-test/suite/multi_source/skip_counter.test b/mysql-test/suite/multi_source/skip_counter.test new file mode 100644 index 00000000000..ceb7eb93f0f --- /dev/null +++ b/mysql-test/suite/multi_source/skip_counter.test @@ -0,0 +1,151 @@ +# +# Test of sql_slave_skip_counter and rpl_max_size +# + +--enable_connect_log + +# Create a schema and a table i +# on the 1st master + +--connect (master1,127.0.0.1,root,,,$SERVER_MYPORT_1) + +--disable_warnings +drop database if exists db; +--enable_warnings +create database db; +create table db.t1 (i int) engine=MyISAM; +--save_master_pos + +# Create the same schema and another table +# on the 2nd master + +--connect (master2,127.0.0.1,root,,,$SERVER_MYPORT_2) + +--disable_warnings +drop database if exists db; +--enable_warnings +create database db; +create table db.t2 (i int) engine=MyISAM; + +--connect (slave,127.0.0.1,root,,,$SERVER_MYPORT_3) +--disable_connect_log + +# Start replication from the first master + +--replace_result $SERVER_MYPORT_1 MYPORT_1 +eval change master 'master1' to +master_port=$SERVER_MYPORT_1, +master_host='127.0.0.1', +master_user='root'; + +start slave 'master1'; +set default_master_connection = 'master1'; +--source include/wait_for_slave_to_start.inc +--sync_with_master 0,'master1' + +# Start replication from the second master + +set default_master_connection = 'master2'; + +--replace_result $SERVER_MYPORT_2 MYPORT_2 +eval change master 'master2' to +master_port=$SERVER_MYPORT_2, +master_host='127.0.0.1', +master_user='root'; + +# the schema creation will be replicated from the 1st master, +# so we want to skip it in the second replication connection. + +# Normally it should have been 2 events, but +# currently Binlog_checkpoint also counts. Maybe we'll need +# to modify the test later + +--let $skip_counter_saved = `select @@global.sql_slave_skip_counter` +--let $max_relay_log_size_saved= `select @@global.max_relay_log_size` +--let $max_binlog_size_saved= `select @@global.max_binlog_size` +set global sql_slave_skip_counter = 2; +select @@global.sql_slave_skip_counter; +select @@session.sql_slave_skip_counter; +set session sql_slave_skip_counter = 3; +select @@global.sql_slave_skip_counter; +select @@session.sql_slave_skip_counter; +set global sql_slave_skip_counter= default; +select @@global.sql_slave_skip_counter; +select @@session.sql_slave_skip_counter; +set global sql_slave_skip_counter= 3; +set default_master_connection = 'master1'; +select @@session.sql_slave_skip_counter; +set default_master_connection = 'qqq'; +select @@session.sql_slave_skip_counter; +set default_master_connection = 'master2'; +select @@session.sql_slave_skip_counter; + +# Test of setting max_relay_log_size +select @@global.max_relay_log_size; +set global max_relay_log_size = 1*1024*1024; +select @@global.max_relay_log_size; +select @@session.max_relay_log_size; +set session max_relay_log_size = 3*1024*1024; +select @@global.max_relay_log_size; +select @@session.max_relay_log_size; +set global max_relay_log_size= default; +select @@global.max_relay_log_size; +select @@session.max_relay_log_size; +set global max_relay_log_size= 3*1024*1024; +set default_master_connection = 'master1'; +select @@session.max_relay_log_size; +set default_master_connection = 'qqq'; +select @@session.max_relay_log_size; +set default_master_connection = 'master2'; +select @@session.max_relay_log_size; +set global max_binlog_size= 4*1024*1024; +select @@global.max_relay_log_size; + + +start slave 'master2'; +--source include/wait_for_slave_to_start.inc +set default_master_connection = ''; + +--enable_connect_log + +--connection master2 +--save_master_pos + +--connection slave + +--disable_connect_log +--sync_with_master 0,'master2' + +# If the skip_counter worked as expected, we should +# get here (replication shouldn't have broken) +# and should see both tables here +# (drop database which came from master2 shoudn't have been executed +# so t1 should still exist) + +show tables in db; + +# Cleanup + +drop database db; +set default_master_connection = 'master1'; +stop slave; + +--source include/wait_for_slave_to_stop.inc +set default_master_connection = 'master2'; +stop slave; + +--source include/wait_for_slave_to_stop.inc +--eval set global sql_slave_skip_counter = $skip_counter_saved +--eval set global max_relay_log_size = $max_relay_log_size_saved +--eval set global max_binlog_size = $max_binlog_size_saved + +--enable_connect_log +--disconnect slave + +--connection master1 +drop database db; +--disconnect master1 + +--connection master2 +drop database db; +--disconnect master2 diff --git a/mysql-test/suite/multi_source/syntax.result b/mysql-test/suite/multi_source/syntax.result new file mode 100644 index 00000000000..b82902096c3 --- /dev/null +++ b/mysql-test/suite/multi_source/syntax.result @@ -0,0 +1,87 @@ +include/master-slave.inc +[connection master] +show slave status; +Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id +show slave '' status; +Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id +show all slaves status; +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period +# +# Check error handling +# +show slave 'qqq' status; +ERROR HY000: There is no master connection 'qqq' +show slave 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' status; +ERROR HY000: There is no master connection 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' +show slave 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' status; +ERROR HY000: Incorrect arguments to MASTER_CONNECTION_NAME +change master 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' to master_host='dummy'; +ERROR HY000: Incorrect arguments to MASTER_CONNECTION_NAME +start slave 'qqq'; +ERROR HY000: There is no master connection 'qqq' +stop slave 'qqq'; +ERROR HY000: There is no master connection 'qqq' +slave 'qqq' start; +ERROR HY000: There is no master connection 'qqq' +slave 'qqq' stop; +ERROR HY000: There is no master connection 'qqq' +flush slave 'qqq'; +ERROR HY000: There is no master connection 'qqq' +reset slave 'qqq'; +ERROR HY000: There is no master connection 'qqq' +select master_pos_wait('master-bin.999999',0,2,'qqq'); +master_pos_wait('master-bin.999999',0,2,'qqq') +NULL +Warnings: +Warning 1617 There is no master connection 'qqq' +select master_pos_wait('master-bin.999999',0,2,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'); +master_pos_wait('master-bin.999999',0,2,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc') +NULL +Warnings: +Warning 1210 Incorrect arguments to MASTER_CONNECTION_NAME +# +# checking usage of default_master_connection; +# +select @@default_master_connection; +@@default_master_connection + +select @@global.default_master_connection; +ERROR HY000: Variable 'default_master_connection' is a SESSION variable +set @@global.default_master_connection='qqq'; +ERROR HY000: Variable 'default_master_connection' is a SESSION variable and can't be used with SET GLOBAL +set @@default_master_connection='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'; +ERROR 42000: Variable 'default_master_connection' can't be set to the value of 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' +select @@default_master_connection; +@@default_master_connection + +set @@default_master_connection='qqq'; +select @@default_master_connection; +@@default_master_connection +qqq +show variables like "default_master_connection"; +Variable_name Value +default_master_connection qqq +show slave status; +ERROR HY000: There is no master connection 'qqq' +select master_pos_wait('master-bin.999999',0,2); +master_pos_wait('master-bin.999999',0,2) +NULL +Warnings: +Warning 1617 There is no master connection 'qqq' +set @@default_master_connection=''; +select master_pos_wait('master-bin.999999',0,2); +master_pos_wait('master-bin.999999',0,2) +-1 +set @@default_master_connection=''; +# +# checking variables +# +show status like "Slave_running"; +Variable_name Value +Slave_running ON +set @@default_master_connection='qqq'; +show status like "Slave_running"; +Variable_name Value +Slave_running +set @@default_master_connection=''; +include/rpl_end.inc diff --git a/mysql-test/suite/multi_source/syntax.test b/mysql-test/suite/multi_source/syntax.test new file mode 100644 index 00000000000..15e862ab607 --- /dev/null +++ b/mysql-test/suite/multi_source/syntax.test @@ -0,0 +1,77 @@ +# Test multi master syntax +source include/master-slave.inc; + +# Check syntax of multi source replication + +show slave status; +show slave '' status; +show all slaves status; + +--echo # +--echo # Check error handling +--echo # + +--error WARN_NO_MASTER_INFO +show slave 'qqq' status; +--error WARN_NO_MASTER_INFO +show slave 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' status; +--error ER_WRONG_ARGUMENTS +show slave 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' status; +--error ER_WRONG_ARGUMENTS +change master 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' to master_host='dummy'; + +--error WARN_NO_MASTER_INFO +start slave 'qqq'; +--error WARN_NO_MASTER_INFO +stop slave 'qqq'; +--error WARN_NO_MASTER_INFO +slave 'qqq' start; +--error WARN_NO_MASTER_INFO +slave 'qqq' stop; +--error WARN_NO_MASTER_INFO +flush slave 'qqq'; +--error WARN_NO_MASTER_INFO +reset slave 'qqq'; + +select master_pos_wait('master-bin.999999',0,2,'qqq'); +select master_pos_wait('master-bin.999999',0,2,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'); + +save_master_pos; +connection slave; +sync_with_master 0,''; +sync_with_master 0 ,''; +sync_with_master 0, ''; + +--echo # +--echo # checking usage of default_master_connection; +--echo # +select @@default_master_connection; + +--error 1238 +select @@global.default_master_connection; +--error 1228 +set @@global.default_master_connection='qqq'; +--error 1231 +set @@default_master_connection='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'; +select @@default_master_connection; +set @@default_master_connection='qqq'; +select @@default_master_connection; +show variables like "default_master_connection"; + +--error WARN_NO_MASTER_INFO +show slave status; +select master_pos_wait('master-bin.999999',0,2); +set @@default_master_connection=''; +select master_pos_wait('master-bin.999999',0,2); + +set @@default_master_connection=''; + +--echo # +--echo # checking variables +--echo # +show status like "Slave_running"; +set @@default_master_connection='qqq'; +show status like "Slave_running"; +set @@default_master_connection=''; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result b/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result index 37d209bbcf6..f2128f8d855 100644 --- a/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result @@ -76,6 +76,8 @@ include/check_slave_is_running.inc *** Test lock wait timeout and purged relay logs *** SET @my_max_relay_log_size= @@global.max_relay_log_size; SET global max_relay_log_size=0; +Warnings: +Warning 1292 Truncated incorrect max_relay_log_size value: '0' include/stop_slave.inc DELETE FROM t2; CHANGE MASTER TO MASTER_LOG_POS=<master_pos_begin>; diff --git a/mysql-test/suite/rpl/r/rpl_filter_dbs_dynamic.result b/mysql-test/suite/rpl/r/rpl_filter_dbs_dynamic.result index 321b8d912e6..eaa2ed9a61d 100644 --- a/mysql-test/suite/rpl/r/rpl_filter_dbs_dynamic.result +++ b/mysql-test/suite/rpl/r/rpl_filter_dbs_dynamic.result @@ -1,9 +1,9 @@ include/master-slave.inc [connection master] SET @@GLOBAL.replicate_do_db="db1"; -ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first SET @@GLOBAL.replicate_ignore_db="db2"; -ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first include/stop_slave.inc SET @@GLOBAL.replicate_do_db="db1"; SET @@GLOBAL.replicate_ignore_db="db2"; diff --git a/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result b/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result index 9eb803d17ea..3d03d36828a 100644 --- a/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result +++ b/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result @@ -1,9 +1,9 @@ include/master-slave.inc [connection master] SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; -ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; -ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first include/stop_slave.inc SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; diff --git a/mysql-test/suite/rpl/r/rpl_filter_wild_tables_dynamic.result b/mysql-test/suite/rpl/r/rpl_filter_wild_tables_dynamic.result index 6858181234e..19d8e513e6f 100644 --- a/mysql-test/suite/rpl/r/rpl_filter_wild_tables_dynamic.result +++ b/mysql-test/suite/rpl/r/rpl_filter_wild_tables_dynamic.result @@ -1,9 +1,9 @@ include/master-slave.inc [connection master] SET @@GLOBAL.replicate_wild_do_table="test.a%"; -ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first SET @@GLOBAL.replicate_wild_ignore_table="test.b%"; -ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first include/stop_slave.inc SET @@GLOBAL.replicate_wild_do_table="test.a%"; SET @@GLOBAL.replicate_wild_ignore_table="test.b%"; diff --git a/mysql-test/suite/rpl/r/rpl_flush_logs.result b/mysql-test/suite/rpl/r/rpl_flush_logs.result index 4fce91a7234..1f543cd9f43 100644 --- a/mysql-test/suite/rpl/r/rpl_flush_logs.result +++ b/mysql-test/suite/rpl/r/rpl_flush_logs.result @@ -8,7 +8,7 @@ flush error logs; # after execute 'flush error logs' statement. # Test if support 'flush relay logs' statement. flush relay logs; -# Check the 'slave-relay-bin.000003' file is created +# Check the 'slave-relay-bin.000003' file is not created # after executed 'flush relay logs' statement. # Make sure binary logs was not be flushed # after execute 'flush relay logs' statement. @@ -30,21 +30,21 @@ flush engine logs; flush binary logs; # Check the 'master-bin.000002' file is created # after executed 'flush binary logs' statement. -# Make sure the 'slave-relay-bin.000006' file does not exist +# Make sure the 'slave-relay-bin.000005' file does not exist # exist before execute 'flush error logs, relay logs' statement. # Test if support to combine all kinds of logs into one statement. flush error logs, relay logs; # Make sure binary logs was not be flushed # after execute 'flush error logs, relay logs' statement. -# Check the 'slave-relay-bin.000006' file is created after +# Check the 'slave-relay-bin.000004' file is created after # execute 'flush error logs, relay logs' statement. -# Make sure the 'slave-relay-bin.000007' and 'slave-relay-bin.000008' +# Make sure the 'slave-relay-bin.000005' and 'slave-relay-bin.000006' # files do not exist before execute 'flush error logs, relay logs' # statement. # Test if 'flush logs' statement works fine and flush all the logs. flush logs; # Check 'master-bin.000003' is created # after execute 'flush logs' statement. -# Check the 'slave-relay-bin.000007' and 'slave-relay-bin.000008' +# Check the 'slave-relay-bin.000005' and 'slave-relay-bin.000006' # files are created after execute 'flush logs' statement. include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_heartbeat.result b/mysql-test/suite/rpl/r/rpl_heartbeat.result index d4bdb77ef0b..b0f36558d10 100644 --- a/mysql-test/suite/rpl/r/rpl_heartbeat.result +++ b/mysql-test/suite/rpl/r/rpl_heartbeat.result @@ -41,8 +41,6 @@ show status like 'Slave_heartbeat_period';; Variable_name Slave_heartbeat_period Value 4.000 set @@global.slave_net_timeout= 3 /* must be a warning */; -Warnings: -Warning 1704 The requested value for the heartbeat period exceeds the value of `slave_net_timeout' seconds. A sensible value for the period should be less than the timeout. reset slave; drop table if exists t1; set @@global.slave_net_timeout= 10; diff --git a/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result b/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result index cc9d1f99f7c..0c274165e1e 100644 --- a/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result +++ b/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result @@ -33,8 +33,6 @@ RESET SLAVE; *** Warning if updated slave_net_timeout < slave_heartbeat_timeout *** SET @@global.slave_net_timeout=FLOOR(SLAVE_HEARTBEAT_TIMEOUT)-1; -Warnings: -Warning 1704 The requested value for the heartbeat period exceeds the value of `slave_net_timeout' seconds. A sensible value for the period should be less than the timeout. SET @@global.slave_net_timeout=@restore_slave_net_timeout; RESET SLAVE; diff --git a/mysql-test/suite/rpl/r/rpl_rotate_logs.result b/mysql-test/suite/rpl/r/rpl_rotate_logs.result index f10e30c698d..783c02b961c 100644 --- a/mysql-test/suite/rpl/r/rpl_rotate_logs.result +++ b/mysql-test/suite/rpl/r/rpl_rotate_logs.result @@ -2,9 +2,9 @@ CALL mtr.add_suppression("Unsafe statement written to the binary log using state start slave; Got one of the listed errors start slave; -ERROR HY000: Could not initialize master info structure; more error messages can be found in the MariaDB error log +ERROR HY000: Could not initialize master info structure for ''; more error messages can be found in the MariaDB error log change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; -ERROR HY000: Could not initialize master info structure; more error messages can be found in the MariaDB error log +ERROR HY000: Could not initialize master info structure for ''; more error messages can be found in the MariaDB error log reset slave; change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; reset master; diff --git a/mysql-test/suite/rpl/r/rpl_row_max_relay_size.result b/mysql-test/suite/rpl/r/rpl_row_max_relay_size.result index 379cea4d3fc..88d68bb50ee 100644 --- a/mysql-test/suite/rpl/r/rpl_row_max_relay_size.result +++ b/mysql-test/suite/rpl/r/rpl_row_max_relay_size.result @@ -10,7 +10,7 @@ reset slave; # # Test 1 # -set @my_max_binlog_size= @@global.max_binlog_size; +set @my_max_binlog_size= @@global.max_binlog_size, @my_max_relay_log_size=@@global.max_relay_log_size; set global max_binlog_size=8192; set global max_relay_log_size=8192-1; Warnings: @@ -36,8 +36,10 @@ include/check_slave_is_running.inc stop slave; reset slave; set global max_relay_log_size=0; +Warnings: +Warning 1292 Truncated incorrect max_relay_log_size value: '0' select @@global.max_relay_log_size; -@@global.max_relay_log_size 0 +@@global.max_relay_log_size 4096 start slave; include/check_slave_is_running.inc # @@ -65,6 +67,7 @@ show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000002 # <Binlog_Do_DB> <Binlog_Ignore_DB> set global max_binlog_size= @my_max_binlog_size; +set global max_relay_log_size= @my_max_relay_log_size; # # End of 4.1 tests # diff --git a/mysql-test/suite/rpl/r/rpl_row_show_relaylog_events.result b/mysql-test/suite/rpl/r/rpl_row_show_relaylog_events.result index a6d691f420e..cd72b489e1a 100644 --- a/mysql-test/suite/rpl/r/rpl_row_show_relaylog_events.result +++ b/mysql-test/suite/rpl/r/rpl_row_show_relaylog_events.result @@ -90,38 +90,38 @@ slave-bin.000001 # Table_map # # table_id: # (test.t1) slave-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F slave-bin.000001 # Query # # COMMIT ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> ******** -show relaylog events in 'slave-relay-bin.000003' from <binlog_start>; -Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000003 # Rotate # # master-bin.000001;pos=4 -slave-relay-bin.000003 # Format_desc # # SERVER_VERSION, BINLOG_VERSION -slave-relay-bin.000003 # Binlog_checkpoint # # master-bin.000001 -slave-relay-bin.000003 # Query # # use `test`; CREATE TABLE t1 (a INT) -slave-relay-bin.000003 # Query # # BEGIN -slave-relay-bin.000003 # Table_map # # table_id: # (test.t1) -slave-relay-bin.000003 # Write_rows # # table_id: # flags: STMT_END_F -slave-relay-bin.000003 # Query # # COMMIT -slave-relay-bin.000003 # Query # # BEGIN -slave-relay-bin.000003 # Table_map # # table_id: # (test.t1) -slave-relay-bin.000003 # Write_rows # # table_id: # flags: STMT_END_F -slave-relay-bin.000003 # Query # # COMMIT -slave-relay-bin.000003 # Query # # BEGIN -slave-relay-bin.000003 # Table_map # # table_id: # (test.t1) -slave-relay-bin.000003 # Write_rows # # table_id: # flags: STMT_END_F -slave-relay-bin.000003 # Query # # COMMIT +show relaylog events in 'slave-relay-bin.000002' from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +slave-relay-bin.000002 # Rotate # # master-bin.000001;pos=4 +slave-relay-bin.000002 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +slave-relay-bin.000002 # Binlog_checkpoint # # master-bin.000001 +slave-relay-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT) +slave-relay-bin.000002 # Query # # BEGIN +slave-relay-bin.000002 # Table_map # # table_id: # (test.t1) +slave-relay-bin.000002 # Write_rows # # table_id: # flags: STMT_END_F +slave-relay-bin.000002 # Query # # COMMIT +slave-relay-bin.000002 # Query # # BEGIN +slave-relay-bin.000002 # Table_map # # table_id: # (test.t1) +slave-relay-bin.000002 # Write_rows # # table_id: # flags: STMT_END_F +slave-relay-bin.000002 # Query # # COMMIT +slave-relay-bin.000002 # Query # # BEGIN +slave-relay-bin.000002 # Table_map # # table_id: # (test.t1) +slave-relay-bin.000002 # Write_rows # # table_id: # flags: STMT_END_F +slave-relay-bin.000002 # Query # # COMMIT ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> LIMIT 1 ******** -show relaylog events in 'slave-relay-bin.000003' from <binlog_start> limit 1; +show relaylog events in 'slave-relay-bin.000002' from <binlog_start> limit 1; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000003 # Rotate # # master-bin.000001;pos=4 +slave-relay-bin.000002 # Rotate # # master-bin.000001;pos=4 ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> LIMIT 1,3 ******** -show relaylog events in 'slave-relay-bin.000003' from <binlog_start> limit 1,3; +show relaylog events in 'slave-relay-bin.000002' from <binlog_start> limit 1,3; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000003 # Format_desc # # SERVER_VERSION, BINLOG_VERSION -slave-relay-bin.000003 # Binlog_checkpoint # # master-bin.000001 -slave-relay-bin.000003 # Query # # use `test`; CREATE TABLE t1 (a INT) +slave-relay-bin.000002 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +slave-relay-bin.000002 # Binlog_checkpoint # # master-bin.000001 +slave-relay-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT) ******** [slave] SHOW RELAYLOG EVENTS ******** show relaylog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000002 # Rotate # # slave-relay-bin.000003;pos=4 +slave-relay-bin.000001 # Rotate # # slave-relay-bin.000002;pos=4 FLUSH LOGS; FLUSH LOGS; DROP TABLE t1; @@ -186,26 +186,26 @@ slave-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F slave-bin.000001 # Query # # COMMIT slave-bin.000001 # Rotate # # slave-bin.000002;pos=4 ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> ******** -show relaylog events in 'slave-relay-bin.000006' from <binlog_start>; +show relaylog events in 'slave-relay-bin.000005' from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000006 # Rotate # # master-bin.000002;pos=4 -slave-relay-bin.000006 # Format_desc # # SERVER_VERSION, BINLOG_VERSION -slave-relay-bin.000006 # Binlog_checkpoint # # master-bin.000001 -slave-relay-bin.000006 # Binlog_checkpoint # # master-bin.000002 -slave-relay-bin.000006 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ +slave-relay-bin.000005 # Rotate # # master-bin.000002;pos=4 +slave-relay-bin.000005 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +slave-relay-bin.000005 # Binlog_checkpoint # # master-bin.000001 +slave-relay-bin.000005 # Binlog_checkpoint # # master-bin.000002 +slave-relay-bin.000005 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> LIMIT 1 ******** -show relaylog events in 'slave-relay-bin.000006' from <binlog_start> limit 1; +show relaylog events in 'slave-relay-bin.000005' from <binlog_start> limit 1; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000006 # Rotate # # master-bin.000002;pos=4 +slave-relay-bin.000005 # Rotate # # master-bin.000002;pos=4 ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> LIMIT 1,3 ******** -show relaylog events in 'slave-relay-bin.000006' from <binlog_start> limit 1,3; +show relaylog events in 'slave-relay-bin.000005' from <binlog_start> limit 1,3; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000006 # Format_desc # # SERVER_VERSION, BINLOG_VERSION -slave-relay-bin.000006 # Binlog_checkpoint # # master-bin.000001 -slave-relay-bin.000006 # Binlog_checkpoint # # master-bin.000002 +slave-relay-bin.000005 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +slave-relay-bin.000005 # Binlog_checkpoint # # master-bin.000001 +slave-relay-bin.000005 # Binlog_checkpoint # # master-bin.000002 ******** [slave] SHOW RELAYLOG EVENTS ******** show relaylog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000005 # Rotate # # master-bin.000002;pos=4 -slave-relay-bin.000005 # Rotate # # slave-relay-bin.000006;pos=4 +slave-relay-bin.000004 # Rotate # # master-bin.000002;pos=4 +slave-relay-bin.000004 # Rotate # # slave-relay-bin.000005;pos=4 include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_skip_replication.result b/mysql-test/suite/rpl/r/rpl_skip_replication.result index c19f9009021..92b5fa5f629 100644 --- a/mysql-test/suite/rpl/r/rpl_skip_replication.result +++ b/mysql-test/suite/rpl/r/rpl_skip_replication.result @@ -10,7 +10,7 @@ SELECT @@global.replicate_events_marked_for_skip; @@global.replicate_events_marked_for_skip replicate SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_SLAVE; -ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first SELECT @@global.replicate_events_marked_for_skip; @@global.replicate_events_marked_for_skip replicate diff --git a/mysql-test/suite/rpl/r/rpl_start_slave_deadlock_sys_vars.result b/mysql-test/suite/rpl/r/rpl_start_slave_deadlock_sys_vars.result deleted file mode 100644 index f69a323f980..00000000000 --- a/mysql-test/suite/rpl/r/rpl_start_slave_deadlock_sys_vars.result +++ /dev/null @@ -1,31 +0,0 @@ -include/master-slave.inc -[connection master] -# connection: slave -SET @save_slave_net_timeout = @@GLOBAL.slave_net_timeout; -STOP SLAVE; -include/wait_for_slave_to_stop.inc -# open an extra connection to the slave -# connection: slave2 -# set debug synchronization point -SET DEBUG_SYNC='fix_slave_net_timeout SIGNAL parked WAIT_FOR go'; -# attempt to set slave_net_timeout, will wait on sync point -SET @@GLOBAL.slave_net_timeout = 100; -# connection: slave -SET DEBUG_SYNC='now WAIT_FOR parked'; -# connection: slave1 -# attempt to start the SQL thread -START SLAVE SQL_THREAD; -# connection: slave -# wait until SQL thread has been started -# sleep a bit so that the SQL thread THD handle is initialized -# signal the set slave_net_timeout to continue -SET DEBUG_SYNC='now SIGNAL go'; -# connection: slave2 -# reap result of set slave_net_timeout -# connection: slave1 -# reap result of starting the SQL thread -# disconnect: slave2 -# connection: slave -# cleanup -SET @@GLOBAL.slave_net_timeout = @save_slave_net_timeout; -include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_stm_max_relay_size.result b/mysql-test/suite/rpl/r/rpl_stm_max_relay_size.result index 379cea4d3fc..88d68bb50ee 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_max_relay_size.result +++ b/mysql-test/suite/rpl/r/rpl_stm_max_relay_size.result @@ -10,7 +10,7 @@ reset slave; # # Test 1 # -set @my_max_binlog_size= @@global.max_binlog_size; +set @my_max_binlog_size= @@global.max_binlog_size, @my_max_relay_log_size=@@global.max_relay_log_size; set global max_binlog_size=8192; set global max_relay_log_size=8192-1; Warnings: @@ -36,8 +36,10 @@ include/check_slave_is_running.inc stop slave; reset slave; set global max_relay_log_size=0; +Warnings: +Warning 1292 Truncated incorrect max_relay_log_size value: '0' select @@global.max_relay_log_size; -@@global.max_relay_log_size 0 +@@global.max_relay_log_size 4096 start slave; include/check_slave_is_running.inc # @@ -65,6 +67,7 @@ show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000002 # <Binlog_Do_DB> <Binlog_Ignore_DB> set global max_binlog_size= @my_max_binlog_size; +set global max_relay_log_size= @my_max_relay_log_size; # # End of 4.1 tests # diff --git a/mysql-test/suite/rpl/r/rpl_stm_mix_show_relaylog_events.result b/mysql-test/suite/rpl/r/rpl_stm_mix_show_relaylog_events.result index 2c93a15a7b3..490c4998b5d 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_mix_show_relaylog_events.result +++ b/mysql-test/suite/rpl/r/rpl_stm_mix_show_relaylog_events.result @@ -78,35 +78,35 @@ slave-bin.000001 # Query # # BEGIN slave-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (3) slave-bin.000001 # Query # # COMMIT ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> ******** -show relaylog events in 'slave-relay-bin.000003' from <binlog_start>; -Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000003 # Rotate # # master-bin.000001;pos=4 -slave-relay-bin.000003 # Format_desc # # SERVER_VERSION, BINLOG_VERSION -slave-relay-bin.000003 # Binlog_checkpoint # # master-bin.000001 -slave-relay-bin.000003 # Query # # use `test`; CREATE TABLE t1 (a INT) -slave-relay-bin.000003 # Query # # BEGIN -slave-relay-bin.000003 # Query # # use `test`; INSERT INTO t1 VALUES (1) -slave-relay-bin.000003 # Query # # COMMIT -slave-relay-bin.000003 # Query # # BEGIN -slave-relay-bin.000003 # Query # # use `test`; INSERT INTO t1 VALUES (2) -slave-relay-bin.000003 # Query # # COMMIT -slave-relay-bin.000003 # Query # # BEGIN -slave-relay-bin.000003 # Query # # use `test`; INSERT INTO t1 VALUES (3) -slave-relay-bin.000003 # Query # # COMMIT +show relaylog events in 'slave-relay-bin.000002' from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +slave-relay-bin.000002 # Rotate # # master-bin.000001;pos=4 +slave-relay-bin.000002 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +slave-relay-bin.000002 # Binlog_checkpoint # # master-bin.000001 +slave-relay-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT) +slave-relay-bin.000002 # Query # # BEGIN +slave-relay-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (1) +slave-relay-bin.000002 # Query # # COMMIT +slave-relay-bin.000002 # Query # # BEGIN +slave-relay-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (2) +slave-relay-bin.000002 # Query # # COMMIT +slave-relay-bin.000002 # Query # # BEGIN +slave-relay-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (3) +slave-relay-bin.000002 # Query # # COMMIT ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> LIMIT 1 ******** -show relaylog events in 'slave-relay-bin.000003' from <binlog_start> limit 1; +show relaylog events in 'slave-relay-bin.000002' from <binlog_start> limit 1; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000003 # Rotate # # master-bin.000001;pos=4 +slave-relay-bin.000002 # Rotate # # master-bin.000001;pos=4 ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> LIMIT 1,3 ******** -show relaylog events in 'slave-relay-bin.000003' from <binlog_start> limit 1,3; +show relaylog events in 'slave-relay-bin.000002' from <binlog_start> limit 1,3; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000003 # Format_desc # # SERVER_VERSION, BINLOG_VERSION -slave-relay-bin.000003 # Binlog_checkpoint # # master-bin.000001 -slave-relay-bin.000003 # Query # # use `test`; CREATE TABLE t1 (a INT) +slave-relay-bin.000002 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +slave-relay-bin.000002 # Binlog_checkpoint # # master-bin.000001 +slave-relay-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT) ******** [slave] SHOW RELAYLOG EVENTS ******** show relaylog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000002 # Rotate # # slave-relay-bin.000003;pos=4 +slave-relay-bin.000001 # Rotate # # slave-relay-bin.000002;pos=4 FLUSH LOGS; FLUSH LOGS; DROP TABLE t1; @@ -165,26 +165,26 @@ slave-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (3) slave-bin.000001 # Query # # COMMIT slave-bin.000001 # Rotate # # slave-bin.000002;pos=4 ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> ******** -show relaylog events in 'slave-relay-bin.000006' from <binlog_start>; +show relaylog events in 'slave-relay-bin.000005' from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000006 # Rotate # # master-bin.000002;pos=4 -slave-relay-bin.000006 # Format_desc # # SERVER_VERSION, BINLOG_VERSION -slave-relay-bin.000006 # Binlog_checkpoint # # master-bin.000001 -slave-relay-bin.000006 # Binlog_checkpoint # # master-bin.000002 -slave-relay-bin.000006 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ +slave-relay-bin.000005 # Rotate # # master-bin.000002;pos=4 +slave-relay-bin.000005 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +slave-relay-bin.000005 # Binlog_checkpoint # # master-bin.000001 +slave-relay-bin.000005 # Binlog_checkpoint # # master-bin.000002 +slave-relay-bin.000005 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> LIMIT 1 ******** -show relaylog events in 'slave-relay-bin.000006' from <binlog_start> limit 1; +show relaylog events in 'slave-relay-bin.000005' from <binlog_start> limit 1; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000006 # Rotate # # master-bin.000002;pos=4 +slave-relay-bin.000005 # Rotate # # master-bin.000002;pos=4 ******** [slave] SHOW RELAYLOG EVENTS IN <FILE> LIMIT 1,3 ******** -show relaylog events in 'slave-relay-bin.000006' from <binlog_start> limit 1,3; +show relaylog events in 'slave-relay-bin.000005' from <binlog_start> limit 1,3; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000006 # Format_desc # # SERVER_VERSION, BINLOG_VERSION -slave-relay-bin.000006 # Binlog_checkpoint # # master-bin.000001 -slave-relay-bin.000006 # Binlog_checkpoint # # master-bin.000002 +slave-relay-bin.000005 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +slave-relay-bin.000005 # Binlog_checkpoint # # master-bin.000001 +slave-relay-bin.000005 # Binlog_checkpoint # # master-bin.000002 ******** [slave] SHOW RELAYLOG EVENTS ******** show relaylog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000005 # Rotate # # master-bin.000002;pos=4 -slave-relay-bin.000005 # Rotate # # slave-relay-bin.000006;pos=4 +slave-relay-bin.000004 # Rotate # # master-bin.000002;pos=4 +slave-relay-bin.000004 # Rotate # # slave-relay-bin.000005;pos=4 include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_flush_logs.test b/mysql-test/suite/rpl/t/rpl_flush_logs.test index 6e9de634157..1d19576d47c 100644 --- a/mysql-test/suite/rpl/t/rpl_flush_logs.test +++ b/mysql-test/suite/rpl/t/rpl_flush_logs.test @@ -31,8 +31,9 @@ connection master; flush relay logs; sync_slave_with_master; ---echo # Check the 'slave-relay-bin.000003' file is created +--echo # Check the 'slave-relay-bin.000003' file is not created --echo # after executed 'flush relay logs' statement. +--error 1 file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000003; connection master; @@ -89,10 +90,10 @@ file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000001; # Test 'flush error logs, relay logs' statement sync_slave_with_master; ---echo # Make sure the 'slave-relay-bin.000006' file does not exist +--echo # Make sure the 'slave-relay-bin.000005' file does not exist --echo # exist before execute 'flush error logs, relay logs' statement. --error 1 -file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000006; +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005; connection master; @@ -107,19 +108,18 @@ file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000003; sync_slave_with_master; ---echo # Check the 'slave-relay-bin.000006' file is created after +--echo # Check the 'slave-relay-bin.000004' file is created after --echo # execute 'flush error logs, relay logs' statement. -file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000006; - +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000004; # Test 'flush logs' statement ---echo # Make sure the 'slave-relay-bin.000007' and 'slave-relay-bin.000008' +--echo # Make sure the 'slave-relay-bin.000005' and 'slave-relay-bin.000006' --echo # files do not exist before execute 'flush error logs, relay logs' --echo # statement. --error 1 -file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000007; +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005; --error 1 -file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000008; +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000006; connection master; @@ -133,9 +133,9 @@ file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000003; sync_slave_with_master; ---echo # Check the 'slave-relay-bin.000007' and 'slave-relay-bin.000008' +--echo # Check the 'slave-relay-bin.000005' and 'slave-relay-bin.000006' --echo # files are created after execute 'flush logs' statement. -file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000007; -file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000008; +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005; +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000006; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_start_slave_deadlock_sys_vars.test b/mysql-test/suite/rpl/t/rpl_start_slave_deadlock_sys_vars.test deleted file mode 100644 index 3eaff761108..00000000000 --- a/mysql-test/suite/rpl/t/rpl_start_slave_deadlock_sys_vars.test +++ /dev/null @@ -1,57 +0,0 @@ -source include/have_debug_sync.inc; -source include/master-slave.inc; - ---echo # connection: slave -connection slave; -SET @save_slave_net_timeout = @@GLOBAL.slave_net_timeout; -STOP SLAVE; -source include/wait_for_slave_to_stop.inc; - ---echo # open an extra connection to the slave -connect(slave2,127.0.0.1,root,,test,$SLAVE_MYPORT,); ---echo # connection: slave2 ---echo # set debug synchronization point -SET DEBUG_SYNC='fix_slave_net_timeout SIGNAL parked WAIT_FOR go'; ---echo # attempt to set slave_net_timeout, will wait on sync point ---send SET @@GLOBAL.slave_net_timeout = 100 - ---echo # connection: slave -connection slave; -SET DEBUG_SYNC='now WAIT_FOR parked'; - ---echo # connection: slave1 -connection slave1; ---echo # attempt to start the SQL thread ---send START SLAVE SQL_THREAD - ---echo # connection: slave -connection slave; ---echo # wait until SQL thread has been started -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for slave thread to start" and info = "START SLAVE SQL_THREAD"; ---source include/wait_condition.inc ---echo # sleep a bit so that the SQL thread THD handle is initialized -sleep 2; ---echo # signal the set slave_net_timeout to continue -SET DEBUG_SYNC='now SIGNAL go'; - ---echo # connection: slave2 -connection slave2; ---echo # reap result of set slave_net_timeout ---reap - ---echo # connection: slave1 -connection slave1; ---echo # reap result of starting the SQL thread ---reap - ---echo # disconnect: slave2 -disconnect slave2; - ---echo # connection: slave -connection slave; ---echo # cleanup -SET @@GLOBAL.slave_net_timeout = @save_slave_net_timeout; - -source include/rpl_end.inc; diff --git a/mysql-test/suite/sys_vars/r/default_master_connection_basic.result b/mysql-test/suite/sys_vars/r/default_master_connection_basic.result new file mode 100644 index 00000000000..78425049324 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/default_master_connection_basic.result @@ -0,0 +1,94 @@ +SET @start_session_value = @@session.default_master_connection; +SELECT @start_session_value; +@start_session_value + +SET @@session.default_master_connection = 'bar'; +SET @@session.default_master_connection = DEFAULT; +SELECT @@session.default_master_connection; +@@session.default_master_connection + +SET @@session.default_master_connection = @start_session_value; +SELECT @@session.default_master_connection = ''; +@@session.default_master_connection = '' +1 +SET @@global.default_master_connection = 'master1'; +ERROR HY000: Variable 'default_master_connection' is a SESSION variable and can't be used with SET GLOBAL +SELECT @@global.default_master_connection; +ERROR HY000: Variable 'default_master_connection' is a SESSION variable +SET @@session.default_master_connection = 'master1'; +SELECT @@session.default_master_connection; +@@session.default_master_connection +master1 +SET @@session.default_master_connection = ''; +SELECT @@session.default_master_connection; +@@session.default_master_connection + +SET @@session.default_master_connection = '1234-5678'; +SELECT @@session.default_master_connection; +@@session.default_master_connection +1234-5678 +SET @@session.default_master_connection = '@!*/"'; +SELECT @@session.default_master_connection; +@@session.default_master_connection +@!*/" +SET @@session.default_master_connection = REPEAT('a',191); +SELECT @@session.default_master_connection; +@@session.default_master_connection +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +SET @@session.default_master_connection = master2; +SELECT @@session.default_master_connection; +@@session.default_master_connection +master2 +SET @@session.default_master_connection = 1; +ERROR 42000: Incorrect argument type to variable 'default_master_connection' +SET @@session.default_master_connection = 65530.30; +ERROR 42000: Incorrect argument type to variable 'default_master_connection' +SET @@session.default_master_connection = FALSE; +ERROR 42000: Incorrect argument type to variable 'default_master_connection' +SELECT @@session.default_master_connection; +@@session.default_master_connection +master2 +SET @@session.default_master_connection = REPEAT('a',192); +ERROR 42000: Variable 'default_master_connection' can't be set to the value of 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +SELECT @@session.default_master_connection; +@@session.default_master_connection +master2 +SET @@session.default_master_connection = NULL; +ERROR 42000: Variable 'default_master_connection' can't be set to the value of 'NULL' +SELECT @@session.default_master_connection; +@@session.default_master_connection +master2 +SELECT @@global.default_master_connection = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='default_master_connection'; +ERROR HY000: Variable 'default_master_connection' is a SESSION variable +SELECT @@session.default_master_connection = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.SESSION_VARIABLES +WHERE VARIABLE_NAME='default_master_connection'; +@@session.default_master_connection = VARIABLE_VALUE +1 +SET @@default_master_connection = 'foo'; +SELECT @@default_master_connection = @@local.default_master_connection; +@@default_master_connection = @@local.default_master_connection +1 +SELECT @@local.default_master_connection = @@session.default_master_connection; +@@local.default_master_connection = @@session.default_master_connection +1 +SET default_master_connection = 'foo'; +SELECT @@default_master_connection; +@@default_master_connection +foo +SET local.default_master_connection = 'foo'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'default_master_connection = 'foo'' at line 1 +SELECT local.default_master_connection; +ERROR 42S02: Unknown table 'local' in field list +SET session.default_master_connection = 'foo'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'default_master_connection = 'foo'' at line 1 +SELECT session.default_master_connection; +ERROR 42S02: Unknown table 'session' in field list +SELECT default_master_connection = @@session.default_master_connection; +ERROR 42S22: Unknown column 'default_master_connection' in 'field list' +SET @@session.default_master_connection = @start_session_value; +SELECT @@session.default_master_connection; +@@session.default_master_connection + diff --git a/mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result b/mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result index d61e9dd20b0..6025e28ccaa 100644 --- a/mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result +++ b/mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result @@ -1,7 +1,7 @@ SET @start_value = @@global.max_relay_log_size; SELECT @start_value; @start_value -0 +1073741824 '#--------------------FN_DYNVARS_082_01------------------------#' SET @@global.max_relay_log_size = 5000; Warnings: @@ -9,7 +9,7 @@ Warning 1292 Truncated incorrect max_relay_log_size value: '5000' SET @@global.max_relay_log_size = DEFAULT; SELECT @@global.max_relay_log_size; @@global.max_relay_log_size -0 +1073741824 '#---------------------FN_DYNVARS_082_02-------------------------#' SET @@global.max_relay_log_size = @start_value; SELECT @@global.max_relay_log_size = 1024; @@ -17,15 +17,17 @@ SELECT @@global.max_relay_log_size = 1024; 0 '#--------------------FN_DYNVARS_082_03------------------------#' SET @@global.max_relay_log_size = 0; +Warnings: +Warning 1292 Truncated incorrect max_relay_log_size value: '0' SELECT @@global.max_relay_log_size; @@global.max_relay_log_size -0 +4096 SET @@global.max_relay_log_size = 1; Warnings: Warning 1292 Truncated incorrect max_relay_log_size value: '1' SELECT @@global.max_relay_log_size; @@global.max_relay_log_size -0 +4096 SET @@global.max_relay_log_size = 1073741824; SELECT @@global.max_relay_log_size; @@global.max_relay_log_size @@ -48,7 +50,7 @@ Warnings: Warning 1292 Truncated incorrect max_relay_log_size value: '-1' SELECT @@global.max_relay_log_size; @@global.max_relay_log_size -0 +4096 SET @@global.max_relay_log_size = 100000000000; Warnings: Warning 1292 Truncated incorrect max_relay_log_size value: '100000000000' @@ -65,7 +67,7 @@ Warnings: Warning 1292 Truncated incorrect max_relay_log_size value: '-1024' SELECT @@global.max_relay_log_size; @@global.max_relay_log_size -0 +4096 SET @@global.max_relay_log_size = 1073741825; Warnings: Warning 1292 Truncated incorrect max_relay_log_size value: '1073741825' @@ -90,9 +92,9 @@ SELECT @@global.max_relay_log_size; 1073741824 '#-------------------FN_DYNVARS_082_05----------------------------#' SET @@session.max_relay_log_size = 4096; -ERROR HY000: Variable 'max_relay_log_size' is a GLOBAL variable and should be set with SET GLOBAL SELECT @@session.max_relay_log_size; -ERROR HY000: Variable 'max_relay_log_size' is a GLOBAL variable +@@session.max_relay_log_size +4096 '#----------------------FN_DYNVARS_082_06------------------------#' SELECT @@global.max_relay_log_size = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -110,11 +112,13 @@ Warnings: Warning 1292 Truncated incorrect max_relay_log_size value: '1' SELECT @@global.max_relay_log_size; @@global.max_relay_log_size -0 +4096 SET @@global.max_relay_log_size = FALSE; +Warnings: +Warning 1292 Truncated incorrect max_relay_log_size value: '0' SELECT @@global.max_relay_log_size; @@global.max_relay_log_size -0 +4096 '#---------------------FN_DYNVARS_082_08----------------------#' SET @@global.max_relay_log_size = 5000; Warnings: @@ -124,7 +128,8 @@ SELECT @@max_relay_log_size = @@global.max_relay_log_size; 1 '#---------------------FN_DYNVARS_082_09----------------------#' SET max_relay_log_size = 6000; -ERROR HY000: Variable 'max_relay_log_size' is a GLOBAL variable and should be set with SET GLOBAL +Warnings: +Warning 1292 Truncated incorrect max_relay_log_size value: '6000' SELECT @@max_relay_log_size; @@max_relay_log_size 4096 @@ -141,4 +146,4 @@ ERROR 42S22: Unknown column 'max_relay_log_size' in 'field list' SET @@global.max_relay_log_size = @start_value; SELECT @@global.max_relay_log_size; @@global.max_relay_log_size -0 +1073741824 diff --git a/mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result b/mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result index e6d9aff7141..0e1d7af5485 100644 --- a/mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result @@ -35,9 +35,6 @@ VARIABLE_VALUE 1024 '#--------------------FN_DYNVARS_165_03-------------------------#' SET @@sql_slave_skip_counter = 10; -ERROR HY000: Variable 'sql_slave_skip_counter' is a GLOBAL variable and should be set with SET GLOBAL SET @@session.sql_slave_skip_counter = 12; -ERROR HY000: Variable 'sql_slave_skip_counter' is a GLOBAL variable and should be set with SET GLOBAL SET @@local.sql_slave_skip_counter = 13; -ERROR HY000: Variable 'sql_slave_skip_counter' is a GLOBAL variable and should be set with SET GLOBAL SET @@global.sql_slave_skip_counter = 0; diff --git a/mysql-test/suite/sys_vars/t/default_master_connection_basic.test b/mysql-test/suite/sys_vars/t/default_master_connection_basic.test new file mode 100644 index 00000000000..3ec39eb82a4 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/default_master_connection_basic.test @@ -0,0 +1,128 @@ +############## mysql-test\t\default_master_connection_basic.test ############### +# +# Implemented in the scope of MDEV-253 +# The variable is SESSION-only +# + +--source include/load_sysvars.inc + +############################################################# +# Save initial value # +############################################################# + +SET @start_session_value = @@session.default_master_connection; +SELECT @start_session_value; + +################################################################### +# Display the DEFAULT value of default_master_connection # +################################################################### + +SET @@session.default_master_connection = 'bar'; +SET @@session.default_master_connection = DEFAULT; +SELECT @@session.default_master_connection; + +################################################################### +# Check the DEFAULT value of default_master_connection # +################################################################### + +SET @@session.default_master_connection = @start_session_value; +SELECT @@session.default_master_connection = ''; + +################################################# +# Check that the GLOBAL scope is not applicable # +################################################# + +--error ER_LOCAL_VARIABLE +SET @@global.default_master_connection = 'master1'; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@global.default_master_connection; + +#################################################################################### +# Change the value of default_master_connection to a valid value for SESSION Scope # +#################################################################################### + +SET @@session.default_master_connection = 'master1'; +SELECT @@session.default_master_connection; +SET @@session.default_master_connection = ''; +SELECT @@session.default_master_connection; +SET @@session.default_master_connection = '1234-5678'; +SELECT @@session.default_master_connection; +SET @@session.default_master_connection = '@!*/"'; +SELECT @@session.default_master_connection; +SET @@session.default_master_connection = REPEAT('a',191); +SELECT @@session.default_master_connection; +SET @@session.default_master_connection = master2; +SELECT @@session.default_master_connection; + + +##################################################################### +# Change the value of default_master_connection to an invalid value # +##################################################################### + +--error ER_WRONG_TYPE_FOR_VAR +SET @@session.default_master_connection = 1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@session.default_master_connection = 65530.30; +--error ER_WRONG_TYPE_FOR_VAR +SET @@session.default_master_connection = FALSE; +SELECT @@session.default_master_connection; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.default_master_connection = REPEAT('a',192); +SELECT @@session.default_master_connection; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.default_master_connection = NULL; +SELECT @@session.default_master_connection; + +############################################################################### +# Check if the value in GLOBAL & SESSION Tables matches value in variable # +############################################################################### + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@global.default_master_connection = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='default_master_connection'; + +SELECT @@session.default_master_connection = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.SESSION_VARIABLES +WHERE VARIABLE_NAME='default_master_connection'; + + +######################################################################################################## +# Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable # +######################################################################################################## + +SET @@default_master_connection = 'foo'; +SELECT @@default_master_connection = @@local.default_master_connection; +SELECT @@local.default_master_connection = @@session.default_master_connection; + + +################################################################################### +# Check if default_master_connection can be accessed with and without @@ sign # +################################################################################### + +SET default_master_connection = 'foo'; +SELECT @@default_master_connection; +--Error ER_PARSE_ERROR +SET local.default_master_connection = 'foo'; +--Error ER_UNKNOWN_TABLE +SELECT local.default_master_connection; +--Error ER_PARSE_ERROR +SET session.default_master_connection = 'foo'; +--Error ER_UNKNOWN_TABLE +SELECT session.default_master_connection; +--Error ER_BAD_FIELD_ERROR +SELECT default_master_connection = @@session.default_master_connection; + + +#################################### +# Restore initial value # +#################################### + +SET @@session.default_master_connection = @start_session_value; +SELECT @@session.default_master_connection; + + +############################################################# +# END OF default_master_connection TESTS # +############################################################# + diff --git a/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test b/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test index e39778baca8..2e8983f5f01 100644 --- a/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test +++ b/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test @@ -105,9 +105,7 @@ SELECT @@global.max_relay_log_size; # Test if accessing session max_relay_log_size gives error # ######################################################################## ---Error ER_GLOBAL_VARIABLE SET @@session.max_relay_log_size = 4096; ---Error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT @@session.max_relay_log_size; @@ -150,7 +148,6 @@ SELECT @@max_relay_log_size = @@global.max_relay_log_size; # Check if max_relay_log_size can be accessed with and without @@ sign # ############################################################################# ---Error ER_GLOBAL_VARIABLE SET max_relay_log_size = 6000; SELECT @@max_relay_log_size; --Error ER_PARSE_ERROR diff --git a/mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test b/mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test index 10ca47133b7..e1ea74f33c3 100644 --- a/mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test @@ -22,6 +22,11 @@ # server-system-variables.html # # # ############################################################################### +# # +# Modification date: 2012-09-30 # +# With implementation of MDEV-253, the variable scope can be session # +# # +############################################################################### --source include/not_embedded.inc --source include/load_sysvars.inc @@ -88,11 +93,8 @@ WHERE VARIABLE_NAME='sql_slave_skip_counter'; # Checking if variable is accessible with session scope # ################################################################### ---Error ER_GLOBAL_VARIABLE SET @@sql_slave_skip_counter = 10; ---Error ER_GLOBAL_VARIABLE SET @@session.sql_slave_skip_counter = 12; ---Error ER_GLOBAL_VARIABLE SET @@local.sql_slave_skip_counter = 13; SET @@global.sql_slave_skip_counter = 0; diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test index 037e2fcaa73..a1df9359d30 100644 --- a/mysql-test/t/flush.test +++ b/mysql-test/t/flush.test @@ -701,3 +701,11 @@ disconnect con1; connection default; COMMIT; DROP TABLE t1; + +--echo # +--echo # Test flushing slave or relay logs twice +--echo # +--error ER_WRONG_USAGE +flush relay logs,relay logs; +--error ER_WRONG_USAGE +flush slave,slave; diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index d477843b22b..2c8cfafb90a 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -553,7 +553,7 @@ select master_pos_wait(); -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT select master_pos_wait(1); -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT -select master_pos_wait(1, 2, 3, 4); +select master_pos_wait(1, 2, 3, 4, 5); -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT select rand(1, 2, 3); diff --git a/mysys/mf_fn_ext.c b/mysys/mf_fn_ext.c index 47fc67cabbd..cbf0d5dd9e4 100644 --- a/mysys/mf_fn_ext.c +++ b/mysys/mf_fn_ext.c @@ -52,3 +52,40 @@ char *fn_ext(const char *name) pos=strchr(gpos,FN_EXTCHAR); DBUG_RETURN((char*) (pos ? pos : strend(gpos))); } /* fn_ext */ + + +/* + Return a pointer to the extension of the filename. + + SYNOPSIS + fn_ext() + name Name of file + + DESCRIPTION + The extension is defined as everything after the last extension character + (normally '.') after the directory name. + + RETURN VALUES + Pointer to to the extension character. If there isn't any extension, + points at the end ASCII(0) of the filename. +*/ + +char *fn_ext2(const char *name) +{ + register const char *pos, *gpos; + DBUG_ENTER("fn_ext"); + DBUG_PRINT("mfunkt",("name: '%s'",name)); + +#if defined(FN_DEVCHAR) || defined(BASKSLASH_MBTAIL) + { + char buff[FN_REFLEN]; + size_t res_length; + gpos= name+ dirname_part(buff,(char*) name, &res_length); + } +#else + if (!(gpos= strrchr(name, FN_LIBCHAR))) + gpos= name; +#endif + pos=strrchr(gpos,FN_EXTCHAR); + DBUG_RETURN((char*) (pos ? pos : strend(gpos))); +} /* fn_ext */ diff --git a/plugin/semisync/semisync_master_plugin.cc b/plugin/semisync/semisync_master_plugin.cc index b6ff23cd1ad..c811cb1cc9e 100644 --- a/plugin/semisync/semisync_master_plugin.cc +++ b/plugin/semisync/semisync_master_plugin.cc @@ -297,10 +297,10 @@ DEF_SHOW_FUNC(avg_trx_wait_time, SHOW_LONG) static SHOW_VAR semi_sync_master_status_vars[]= { {"Rpl_semi_sync_master_status", (char*) &SHOW_FNAME(status), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {"Rpl_semi_sync_master_clients", (char*) &SHOW_FNAME(clients), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {"Rpl_semi_sync_master_yes_tx", (char*) &rpl_semi_sync_master_yes_transactions, SHOW_LONG}, @@ -309,7 +309,7 @@ static SHOW_VAR semi_sync_master_status_vars[]= { SHOW_LONG}, {"Rpl_semi_sync_master_wait_sessions", (char*) &SHOW_FNAME(wait_sessions), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {"Rpl_semi_sync_master_no_times", (char*) &rpl_semi_sync_master_off_times, SHOW_LONG}, @@ -321,22 +321,22 @@ static SHOW_VAR semi_sync_master_status_vars[]= { SHOW_LONG}, {"Rpl_semi_sync_master_tx_wait_time", (char*) &SHOW_FNAME(trx_wait_time), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {"Rpl_semi_sync_master_tx_waits", (char*) &SHOW_FNAME(trx_wait_num), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {"Rpl_semi_sync_master_tx_avg_wait_time", (char*) &SHOW_FNAME(avg_trx_wait_time), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {"Rpl_semi_sync_master_net_wait_time", (char*) &SHOW_FNAME(net_wait_time), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {"Rpl_semi_sync_master_net_waits", (char*) &SHOW_FNAME(net_wait_num), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {"Rpl_semi_sync_master_net_avg_wait_time", (char*) &SHOW_FNAME(avg_net_wait_time), - SHOW_FUNC}, + SHOW_SIMPLE_FUNC}, {NULL, NULL, SHOW_LONG}, }; diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index b41c9e2cda0..f107914f738 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -190,7 +190,6 @@ pre_init_event_thread(THD* thd) my_net_init(&thd->net, NULL); thd->security_ctx->set_user((char*)"event_scheduler"); thd->net.read_timeout= slave_net_timeout; - thd->slave_thread= 0; thd->variables.option_bits|= OPTION_AUTO_IS_NULL; thd->client_capabilities|= CLIENT_MULTI_RESULTS; mysql_mutex_lock(&LOCK_thread_count); diff --git a/sql/item_create.cc b/sql/item_create.cc index 96837a8f262..07e7f7b7ff9 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -4393,27 +4393,34 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name, if (item_list != NULL) arg_count= item_list->elements; + if (arg_count < 2 || arg_count > 4) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return func; + } + + thd->lex->safe_to_cache_query= 0; + + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); switch (arg_count) { case 2: { - Item *param_1= item_list->pop(); - Item *param_2= item_list->pop(); func= new (thd->mem_root) Item_master_pos_wait(param_1, param_2); - thd->lex->safe_to_cache_query= 0; break; } case 3: { - Item *param_1= item_list->pop(); - Item *param_2= item_list->pop(); Item *param_3= item_list->pop(); func= new (thd->mem_root) Item_master_pos_wait(param_1, param_2, param_3); - thd->lex->safe_to_cache_query= 0; break; } - default: + case 4: { - my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + Item *param_3= item_list->pop(); + Item *param_4= item_list->pop(); + func= new (thd->mem_root) Item_master_pos_wait(param_1, param_2, param_3, + param_4); break; } } diff --git a/sql/item_func.cc b/sql/item_func.cc index 441eb37d701..5db91cd4231 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3866,13 +3866,45 @@ longlong Item_master_pos_wait::val_int() #ifdef HAVE_REPLICATION longlong pos = (ulong)args[1]->val_int(); longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ; - if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2) + String connection_name_buff; + LEX_STRING connection_name; + Master_info *mi; + if (arg_count == 4) + { + String *con; + if (!(con= args[3]->val_str(&connection_name_buff))) + goto err; + + connection_name.str= (char*) con->ptr(); + connection_name.length= con->length(); + if (check_master_connection_name(&connection_name)) + { + my_error(ER_WRONG_ARGUMENTS, MYF(ME_JUST_WARNING), + "MASTER_CONNECTION_NAME"); + goto err; + } + } + else + connection_name= thd->variables.default_master_connection; + + if (!(mi= master_info_index->get_master_info(&connection_name, + MYSQL_ERROR::WARN_LEVEL_WARN))) + goto err; + if ((event_count = mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2) { null_value = 1; event_count=0; } #endif return event_count; + +#ifdef HAVE_REPLICATION +err: + { + null_value = 1; + return 0; + } +#endif } diff --git a/sql/item_func.h b/sql/item_func.h index 586444e0e4e..07b246b3ccd 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -496,6 +496,8 @@ public: { collation.set_numeric(); fix_char_length(21); } Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { collation.set_numeric(); fix_char_length(21); } + Item_int_func(Item *a,Item *b,Item *c, Item *d) :Item_func(a,b,c,d) + { collation.set_numeric(); fix_char_length(21); } Item_int_func(List<Item> &list) :Item_func(list) { collation.set_numeric(); fix_char_length(21); } Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) @@ -1522,6 +1524,7 @@ class Item_master_pos_wait :public Item_int_func public: Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {} Item_master_pos_wait(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {} + Item_master_pos_wait(Item *a,Item *b, Item *c, Item *d) :Item_int_func(a,b,c,d) {} longlong val_int(); const char *func_name() const { return "master_pos_wait"; } void fix_length_and_dec() { max_length=21; maybe_null=1;} diff --git a/sql/lex.h b/sql/lex.h index 9bf4c439cb6..dab9e2adbc4 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -514,6 +514,7 @@ static SYMBOL symbols[] = { { "SIGNED", SYM(SIGNED_SYM)}, { "SIMPLE", SYM(SIMPLE_SYM)}, { "SLAVE", SYM(SLAVE)}, + { "SLAVES", SYM(SLAVES)}, { "SLOW", SYM(SLOW)}, { "SNAPSHOT", SYM(SNAPSHOT_SYM)}, { "SMALLINT", SYM(SMALLINT)}, diff --git a/sql/log.cc b/sql/log.cc index e4db7b2eb0f..e664540f0d6 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -40,6 +40,7 @@ #include "rpl_rli.h" #include "sql_audit.h" #include "log_slow.h" +#include "mysqld.h" #include <my_dir.h> #include <stdarg.h> @@ -3597,11 +3598,11 @@ err: /** Delete all logs refered to in the index file. - Start writing to a new log file. The new index file will only contain this file. - @param thd Thread + @param thd Thread + @param create_new_log 1 if we should start writing to a new log file @note If not called from slave thread, write start event to new log @@ -3612,7 +3613,7 @@ err: 1 error */ -bool MYSQL_BIN_LOG::reset_logs(THD* thd) +bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log) { LOG_INFO linfo; bool error=0; @@ -3779,7 +3780,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) goto err; } } - if (!open_index_file(index_file_name, 0, FALSE)) + if (create_new_log && !open_index_file(index_file_name, 0, FALSE)) if ((error= open(save_name, log_type, 0, io_cache_type, max_size, 0, FALSE))) goto err; my_free((void *) save_name); @@ -3865,7 +3866,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) DBUG_ENTER("purge_first_log"); DBUG_ASSERT(is_open()); - DBUG_ASSERT(rli->slave_running == 1); + DBUG_ASSERT(rli->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT); DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name)); mysql_mutex_lock(&LOCK_index); @@ -4702,7 +4703,7 @@ bool MYSQL_BIN_LOG::append(Log_event* ev) DBUG_PRINT("info",("max_size: %lu",max_size)); if (flush_and_sync(0)) goto err; - if ((uint) my_b_append_tell(&log_file) > max_size) + if (my_b_append_tell(&log_file) > max_size) error= new_file_without_locking(); err: mysql_mutex_unlock(&LOCK_log); @@ -4733,7 +4734,7 @@ bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...) DBUG_PRINT("info",("max_size: %lu",max_size)); if (flush_and_sync(0)) goto err; - if ((uint) my_b_append_tell(&log_file) > max_size) + if (my_b_append_tell(&log_file) > max_size) error= new_file_without_locking(); err: if (!error) @@ -6980,16 +6981,33 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer, time_t skr; struct tm tm_tmp; struct tm *start; + THD *thd; + int tag_length= 0; + char tag[NAME_LEN]; DBUG_ENTER("print_buffer_to_file"); DBUG_PRINT("enter",("buffer: %s", buffer)); + if (mysqld_server_initialized && (thd= current_thd)) + { + if (thd->connection_name.length) + { + /* + Add tag for slaves so that the user can see from which connection + the error originates. + */ + tag_length= my_snprintf(tag, sizeof(tag), ER(ER_MASTER_LOG_PREFIX), + (int) thd->connection_name.length, + thd->connection_name.str); + } + } + mysql_mutex_lock(&LOCK_error_log); skr= my_time(0); localtime_r(&skr, &tm_tmp); start=&tm_tmp; - fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %.*s\n", + fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %.*s%.*s\n", start->tm_year % 100, start->tm_mon+1, start->tm_mday, @@ -6998,6 +7016,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer, start->tm_sec, (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ? "Warning" : "Note"), + tag_length, tag, (int) length, buffer); fflush(stderr); diff --git a/sql/log.h b/sql/log.h index cd1845908ef..0e887b48462 100644 --- a/sql/log.h +++ b/sql/log.h @@ -502,11 +502,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG The max size before rotation (usable only if log_type == LOG_BIN: binary logs and relay logs). For a binlog, max_size should be max_binlog_size. - For a relay log, it should be max_relay_log_size if this is non-zero, - max_binlog_size otherwise. max_size is set in init(), and dynamically changed (when one does SET - GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and - fix_max_relay_log_size). + GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) from sys_vars.cc */ ulong max_size; // current file sequence number for load data infile binary logging @@ -748,7 +745,7 @@ public: int register_create_index_entry(const char* entry); int purge_index_entry(THD *thd, ulonglong *decrease_log_space, bool need_mutex); - bool reset_logs(THD* thd); + bool reset_logs(THD* thd, bool create_new_log); void close(uint exiting); void clear_inuse_flag_when_closing(File file); diff --git a/sql/log_event.cc b/sql/log_event.cc index 132f778ee08..e802c7db16e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -906,9 +906,9 @@ int Log_event::do_update_pos(Relay_log_info *rli) Log_event::enum_skip_reason Log_event::do_shall_skip(Relay_log_info *rli) { - DBUG_PRINT("info", ("ev->server_id=%lu, ::server_id=%lu," - " rli->replicate_same_server_id=%d," - " rli->slave_skip_counter=%d", + DBUG_PRINT("info", ("ev->server_id: %lu, ::server_id: %lu," + " rli->replicate_same_server_id: %d," + " rli->slave_skip_counter: %lu", (ulong) server_id, (ulong) ::server_id, rli->replicate_same_server_id, rli->slave_skip_counter)); @@ -11247,6 +11247,9 @@ Heartbeat_log_event::Heartbeat_log_event(const char* buf, uint event_len, There is a dummy replacement for this in the embedded library that returns FALSE; this is used by XtraDB to allow it to access replication stuff while still being able to use the same plugin in both stand-alone and embedded. + + In this function it's ok to use active_mi, as this is only called for + the main replication server. */ bool rpl_get_position_info(const char **log_file_name, ulonglong *log_pos, const char **group_relay_log_name, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 96ea789edd7..24408849eed 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -52,6 +52,7 @@ #include "des_key_file.h" // load_des_key_file #include "sql_manager.h" // stop_handle_manager, start_handle_manager #include "sql_expression_cache.h" // subquery_cache_miss, subquery_cache_hit +#include "sys_vars_shared.h" #include <m_ctype.h> #include <my_dir.h> @@ -469,7 +470,7 @@ ulong back_log, connect_timeout, concurrency, server_id; ulong table_cache_size, table_def_size; ulong what_to_log; ulong slow_launch_time, slave_open_temp_tables; -ulong open_files_limit, max_binlog_size, max_relay_log_size; +ulong open_files_limit, max_binlog_size; ulong slave_trans_retries; uint slave_net_timeout; ulong slave_exec_mode_options; @@ -495,6 +496,7 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0; ulong max_connections, max_connect_errors; ulong extra_max_connections; +ulong slave_retried_transactions; ulonglong denied_connections; my_decimal decimal_zero; @@ -673,8 +675,7 @@ pthread_attr_t connection_attrib; mysql_mutex_t LOCK_server_started; mysql_cond_t COND_server_started; -int mysqld_server_started= 0; - +int mysqld_server_started=0, mysqld_server_initialized= 0; File_parser_dummy_hook file_parser_dummy_hook; /* replication parameters, if master_host is not NULL, we are a slave */ @@ -1761,7 +1762,12 @@ void clean_up(bool print_message) if (cleanup_done++) return; /* purecov: inspected */ - close_active_mi(); +#ifdef HAVE_REPLICATION + // We must call end_slave() as clean_up may have been called during startup + end_slave(); + if (use_slave_mask) + bitmap_free(&slave_error_mask); +#endif stop_handle_manager(); release_ddl_log(); @@ -1776,10 +1782,6 @@ void clean_up(bool print_message) injector::free_instance(); mysql_bin_log.cleanup(); -#ifdef HAVE_REPLICATION - if (use_slave_mask) - bitmap_free(&slave_error_mask); -#endif my_tz_free(); my_dboptions_cache_free(); #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -3378,8 +3380,8 @@ SHOW_VAR com_status_vars[]= { {"show_user_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_USER_STATS]), SHOW_LONG_STATUS}, {"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS}, {"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS}, - {"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS}, - {"slave_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS}, + {"start_all_slaves", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_ALL_START]), SHOW_LONG_STATUS}, + {"start_slave", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS}, {"stmt_close", (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS}, {"stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS}, {"stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS}, @@ -3387,6 +3389,8 @@ SHOW_VAR com_status_vars[]= { {"stmt_reprepare", (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS}, {"stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS}, {"stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS}, + {"stop_all_slaves", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_ALL_STOP]), SHOW_LONG_STATUS}, + {"stop_slave", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS}, {"truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS}, {"uninstall_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS}, {"unlock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS}, @@ -4626,6 +4630,7 @@ int mysqld_main(int argc, char **argv) } #endif + mysqld_server_started= mysqld_server_initialized= 0; orig_argc= argc; orig_argv= argv; my_getopt_use_args_separator= TRUE; @@ -4890,16 +4895,6 @@ int mysqld_main(int argc, char **argv) opt_skip_slave_start= 1; binlog_unsafe_map_init(); - /* - init_slave() must be called after the thread keys are created. - Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other - places) assume that active_mi != 0, so let's fail if it's 0 (out of - memory); a message has already been printed. - */ - if (init_slave() && !active_mi) - { - unireg_abort(1); - } #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE initialize_performance_schema_acl(opt_bootstrap); @@ -4917,9 +4912,17 @@ int mysqld_main(int argc, char **argv) execute_ddl_log_recovery(); + /* + We must have LOCK_open before LOCK_global_system_variables because + LOCK_open is held while sql_plugin.c::intern_sys_var_ptr() is called. + */ + mysql_mutex_record_order(&LOCK_open, &LOCK_global_system_variables); + if (Events::init(opt_noacl || opt_bootstrap)) unireg_abort(1); + mysqld_server_initialized= 1; + if (opt_bootstrap) { select_thread_in_use= 0; // Allow 'kill' to work @@ -4932,21 +4935,27 @@ int mysqld_main(int argc, char **argv) exit(0); } } + + create_shutdown_thread(); + start_handle_manager(); + + /* + init_slave() must be called after the thread keys are created. + Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other + places) assume that active_mi != 0, so let's fail if it's 0 (out of + memory); a message has already been printed. + */ + if (init_slave() && !active_mi) + { + unireg_abort(1); + } + if (opt_init_file && *opt_init_file) { if (read_init_file(opt_init_file)) unireg_abort(1); } - /* - We must have LOCK_open before LOCK_global_system_variables because - LOCK_open is hold while sql_plugin.c::intern_sys_var_ptr() is called. - */ - mysql_mutex_record_order(&LOCK_open, &LOCK_global_system_variables); - - create_shutdown_thread(); - start_handle_manager(); - sql_print_information(ER_DEFAULT(ER_STARTUP),my_progname,server_version, ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysqld_unix_port), @@ -6524,63 +6533,53 @@ static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff) static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff) { + Master_info *mi; var->type= SHOW_MY_BOOL; - mysql_mutex_lock(&LOCK_active_mi); var->value= buff; - *((my_bool *)buff)= (my_bool) (active_mi && - active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT && - active_mi->rli.slave_running); - mysql_mutex_unlock(&LOCK_active_mi); - return 0; -} - -static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff) -{ - /* - TODO: with multimaster, have one such counter per line in - SHOW SLAVE STATUS, and have the sum over all lines here. - */ mysql_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - var->type= SHOW_LONG; - var->value= buff; - mysql_mutex_lock(&active_mi->rli.data_lock); - *((long *)buff)= (long)active_mi->rli.retried_trans; - mysql_mutex_unlock(&active_mi->rli.data_lock); - } + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_NOTE); + if (mi) + *((my_bool *)buff)= (my_bool) (mi->slave_running == + MYSQL_SLAVE_RUN_CONNECT && + mi->rli.slave_running); else var->type= SHOW_UNDEF; mysql_mutex_unlock(&LOCK_active_mi); return 0; } + static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff) { + Master_info *mi; + var->type= SHOW_LONGLONG; + var->value= buff; mysql_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - var->type= SHOW_LONGLONG; - var->value= buff; - mysql_mutex_lock(&active_mi->rli.data_lock); - *((longlong *)buff)= active_mi->received_heartbeats; - mysql_mutex_unlock(&active_mi->rli.data_lock); - } + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_NOTE); + if (mi) + *((longlong *)buff)= mi->received_heartbeats; else var->type= SHOW_UNDEF; mysql_mutex_unlock(&LOCK_active_mi); return 0; } + static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff) { + Master_info *mi; + var->type= SHOW_CHAR; + var->value= buff; mysql_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - var->type= SHOW_CHAR; - var->value= buff; - sprintf(buff, "%.3f", active_mi->heartbeat_period); - } + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_NOTE); + if (mi) + sprintf(buff, "%.3f", mi->heartbeat_period); else var->type= SHOW_UNDEF; mysql_mutex_unlock(&LOCK_active_mi); @@ -6941,7 +6940,7 @@ SHOW_VAR status_vars[]= { {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS}, {"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS}, {"Com", (char*) com_status_vars, SHOW_ARRAY}, - {"Compression", (char*) &show_net_compression, SHOW_FUNC}, + {"Compression", (char*) &show_net_compression, SHOW_SIMPLE_FUNC}, {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH}, {"Cpu_time", (char*) offsetof(STATUS_VAR, cpu_time), SHOW_DOUBLE_STATUS}, {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS}, @@ -6995,13 +6994,13 @@ SHOW_VAR status_vars[]= { {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH}, {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH}, {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH}, - {"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC}, - {"Open_tables", (char*) &show_open_tables, SHOW_FUNC}, + {"Open_table_definitions", (char*) &show_table_definitions, SHOW_SIMPLE_FUNC}, + {"Open_tables", (char*) &show_open_tables, SHOW_SIMPLE_FUNC}, {"Opened_files", (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH}, {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS}, {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS}, {"Opened_views", (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS}, - {"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_FUNC}, + {"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_SIMPLE_FUNC}, {"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS}, {"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS}, {"Rows_tmp_read", (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS}, @@ -7015,10 +7014,10 @@ SHOW_VAR status_vars[]= { {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH}, {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH}, #endif /*HAVE_QUERY_CACHE*/ - {"Queries", (char*) &show_queries, SHOW_FUNC}, + {"Queries", (char*) &show_queries, SHOW_SIMPLE_FUNC}, {"Questions", (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS}, #ifdef HAVE_REPLICATION - {"Rpl_status", (char*) &show_rpl_status, SHOW_FUNC}, + {"Rpl_status", (char*) &show_rpl_status, SHOW_SIMPLE_FUNC}, #endif {"Select_full_join", (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS}, {"Select_full_range_join", (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS}, @@ -7027,10 +7026,10 @@ SHOW_VAR status_vars[]= { {"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS}, {"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_LONG}, #ifdef HAVE_REPLICATION - {"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC}, - {"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_FUNC}, - {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_FUNC}, - {"Slave_running", (char*) &show_slave_running, SHOW_FUNC}, + {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG}, + {"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_SIMPLE_FUNC}, + {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_SIMPLE_FUNC}, + {"Slave_running", (char*) &show_slave_running, SHOW_SIMPLE_FUNC}, #endif {"Slow_launch_threads", (char*) &slow_launch_threads, SHOW_LONG}, {"Slow_queries", (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS}, @@ -7040,29 +7039,29 @@ SHOW_VAR status_vars[]= { {"Sort_scan", (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS}, #ifdef HAVE_OPENSSL #ifndef EMBEDDED_LIBRARY - {"Ssl_accept_renegotiates", (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_FUNC}, - {"Ssl_accepts", (char*) &show_ssl_ctx_sess_accept, SHOW_FUNC}, - {"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_FUNC}, - {"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_FUNC}, - {"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_FUNC}, - {"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_FUNC}, - {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_FUNC}, - {"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_FUNC}, - {"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_FUNC}, - {"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_FUNC}, - {"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_FUNC}, - {"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_FUNC}, - {"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_FUNC}, - {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_FUNC}, - {"Ssl_session_cache_mode", (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_FUNC}, - {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_FUNC}, - {"Ssl_session_cache_size", (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_FUNC}, - {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_FUNC}, - {"Ssl_sessions_reused", (char*) &show_ssl_session_reused, SHOW_FUNC}, - {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_FUNC}, - {"Ssl_verify_depth", (char*) &show_ssl_get_verify_depth, SHOW_FUNC}, - {"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_FUNC}, - {"Ssl_version", (char*) &show_ssl_get_version, SHOW_FUNC}, + {"Ssl_accept_renegotiates", (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_SIMPLE_FUNC}, + {"Ssl_accepts", (char*) &show_ssl_ctx_sess_accept, SHOW_SIMPLE_FUNC}, + {"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_SIMPLE_FUNC}, + {"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_SIMPLE_FUNC}, + {"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_SIMPLE_FUNC}, + {"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_SIMPLE_FUNC}, + {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_SIMPLE_FUNC}, + {"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_SIMPLE_FUNC}, + {"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_SIMPLE_FUNC}, + {"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_SIMPLE_FUNC}, + {"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_SIMPLE_FUNC}, + {"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_mode", (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_size", (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_SIMPLE_FUNC}, + {"Ssl_sessions_reused", (char*) &show_ssl_session_reused, SHOW_SIMPLE_FUNC}, + {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_SIMPLE_FUNC}, + {"Ssl_verify_depth", (char*) &show_ssl_get_verify_depth, SHOW_SIMPLE_FUNC}, + {"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_SIMPLE_FUNC}, + {"Ssl_version", (char*) &show_ssl_get_version, SHOW_SIMPLE_FUNC}, #endif #endif /* HAVE_OPENSSL */ {"Syncs", (char*) &my_sync_count, SHOW_LONG_NOFLUSH}, @@ -7080,16 +7079,16 @@ SHOW_VAR status_vars[]= { {"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG}, #endif #ifdef HAVE_POOL_OF_THREADS - {"Threadpool_idle_threads", (char *) &show_threadpool_idle_threads, SHOW_FUNC}, + {"Threadpool_idle_threads", (char *) &show_threadpool_idle_threads, SHOW_SIMPLE_FUNC}, {"Threadpool_threads", (char *) &tp_stats.num_worker_threads, SHOW_INT}, #endif {"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_NOFLUSH}, {"Threads_connected", (char*) &connection_count, SHOW_INT}, {"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH}, {"Threads_running", (char*) &thread_running, SHOW_INT}, - {"Uptime", (char*) &show_starttime, SHOW_FUNC}, + {"Uptime", (char*) &show_starttime, SHOW_SIMPLE_FUNC}, #ifdef ENABLED_PROFILING - {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_FUNC}, + {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_SIMPLE_FUNC}, #endif {NullS, NullS, SHOW_LONG} }; @@ -7288,6 +7287,7 @@ static int mysql_init_variables(void) protocol_version= PROTOCOL_VERSION; what_to_log= ~ (1L << (uint) COM_TIME); refresh_version= 1L; /* Increments on each reload */ + denied_connections= 0; executed_events= 0; global_query_id= thread_id= 1L; my_atomic_rwlock_init(&global_query_id_lock); @@ -7315,6 +7315,7 @@ static int mysql_init_variables(void) relay_log_info_file= (char*) "relay-log.info"; report_user= report_password = report_host= 0; /* TO BE DELETED */ opt_relay_logname= opt_relaylog_index_name= 0; + slave_retried_transactions= 0; /* Variables in libraries */ charsets_dir= 0; @@ -8007,8 +8008,27 @@ static int get_options(int *argc_ptr, char ***argv_ptr) if (!max_long_data_size_used) max_long_data_size= global_system_variables.max_allowed_packet; - /* Rember if max_user_connections was 0 at startup */ + /* Remember if max_user_connections was 0 at startup */ max_user_connections_checking= global_system_variables.max_user_connections != 0; + + { + sys_var *max_relay_log_size_var, *max_binlog_size_var; + /* If max_relay_log_size is 0, then set it to max_binlog_size */ + if (!global_system_variables.max_relay_log_size) + global_system_variables.max_relay_log_size= max_binlog_size; + + /* + Fix so that DEFAULT and limit checking works with max_relay_log_size + (Yes, this is a hack, but it's required as the definition of + max_relay_log_size allows it to be set to 0). + */ + max_relay_log_size_var= intern_find_sys_var("max_relay_log_size", 0); + max_binlog_size_var= intern_find_sys_var("max_binlog_size", 0); + max_relay_log_size_var->option.min_value= + max_binlog_size_var->option.min_value; + max_relay_log_size_var->option.def_value= + max_binlog_size_var->option.def_value; + } return 0; } diff --git a/sql/mysqld.h b/sql/mysqld.h index 7a24b56dcb7..430811a956c 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -95,6 +95,7 @@ extern my_bool opt_safe_user_create; extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap; extern my_bool opt_slave_compressed_protocol, use_temp_pool; extern ulong slave_exec_mode_options; +extern ulong slave_retried_transactions; extern ulonglong slave_type_conversions_options; extern my_bool read_only, opt_readonly; extern my_bool lower_case_file_system; @@ -169,7 +170,7 @@ extern ulong max_prepared_stmt_count, prepared_stmt_count; extern ulong open_files_limit; extern ulonglong binlog_cache_size, binlog_stmt_cache_size; extern ulonglong max_binlog_cache_size, max_binlog_stmt_cache_size; -extern ulong max_binlog_size, max_relay_log_size; +extern ulong max_binlog_size; extern ulong slave_max_allowed_packet; extern ulong opt_binlog_rows_event_max_size; extern ulong rpl_recovery_rank, thread_cache_size; @@ -198,7 +199,7 @@ extern handlerton *myisam_hton; extern handlerton *heap_hton; extern const char *load_default_groups[]; extern struct my_option my_long_options[]; -extern int mysqld_server_started; +extern int mysqld_server_started, mysqld_server_initialized; extern "C" MYSQL_PLUGIN_IMPORT int orig_argc; extern "C" MYSQL_PLUGIN_IMPORT char **orig_argv; extern pthread_attr_t connection_attrib; diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 3c5a99121fa..e004e3495c7 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -20,6 +20,8 @@ #include "unireg.h" // REQUIRED by other includes #include "rpl_mi.h" #include "slave.h" // SLAVE_MAX_HEARTBEAT_PERIOD +#include "strfunc.h" +#include "sql_repl.h" #ifdef HAVE_REPLICATION @@ -27,7 +29,8 @@ static void init_master_log_pos(Master_info* mi); -Master_info::Master_info(bool is_slave_recovery) +Master_info::Master_info(LEX_STRING *connection_name_arg, + bool is_slave_recovery) :Slave_reporting_capability("I/O"), ssl(0), ssl_verify_server_cert(1), fd(-1), io_thd(0), rli(is_slave_recovery), port(MYSQL_PORT), @@ -40,6 +43,24 @@ Master_info::Master_info(bool is_slave_recovery) ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0; ssl_cipher[0]= 0; ssl_key[0]= 0; + /* + Store connection name and lower case connection name + It's safe to ignore any OMM errors as this is checked by error() + */ + connection_name.length= cmp_connection_name.length= + connection_name_arg->length; + if ((connection_name.str= (char*) my_malloc(connection_name_arg->length*2+2, + MYF(MY_WME)))) + { + cmp_connection_name.str= (connection_name.str + + connection_name_arg->length+1); + strmake(connection_name.str, connection_name_arg->str, + connection_name.length); + memcpy(cmp_connection_name.str, connection_name_arg->str, + connection_name.length+1); + my_casedn_str(system_charset_info, cmp_connection_name.str); + } + my_init_dynamic_array(&ignore_server_ids, sizeof(::server_id), 16, 16); bzero((char*) &file, sizeof(file)); mysql_mutex_init(key_master_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST); @@ -55,6 +76,7 @@ Master_info::Master_info(bool is_slave_recovery) Master_info::~Master_info() { + my_free(connection_name.str); delete_dynamic(&ignore_server_ids); mysql_mutex_destroy(&run_lock); mysql_mutex_destroy(&data_lock); @@ -407,7 +429,7 @@ file '%s')", fname); mi->master_log_name, (ulong) mi->master_log_pos)); - mi->rli.mi = mi; + mi->rli.mi= mi; if (init_relay_log_info(&mi->rli, slave_info_fname)) goto err; @@ -560,5 +582,594 @@ void end_master_info(Master_info* mi) DBUG_VOID_RETURN; } +/* Multi-Master By P.Linux */ +uchar *get_key_master_info(Master_info *mi, size_t *length, + my_bool not_used __attribute__((unused))) +{ + /* Return lower case name */ + *length= mi->cmp_connection_name.length; + return (uchar*) mi->cmp_connection_name.str; +} + +void free_key_master_info(Master_info *mi) +{ + DBUG_ENTER("free_key_master_info"); + terminate_slave_threads(mi,SLAVE_FORCE_ALL); + end_master_info(mi); + delete mi; + DBUG_VOID_RETURN; +} + +/** + Check if connection name for master_info is valid. + + It's valid if it's a valid system name of length less than + MAX_CONNECTION_NAME. + + @return + 0 ok + 1 error +*/ + +bool check_master_connection_name(LEX_STRING *name) +{ + if (name->length >= MAX_CONNECTION_NAME) + return 1; + return 0; +} + + +/** + Create a log file with a given suffix. + + @param + res_file_name Store result here + length Length of res_file_name buffer + info_file Original file name (prefix) + append 1 if we should add suffix last (not before ext) + suffix Suffix + + @note + The suffix is added before the extension of the file name prefixed with '-'. + The suffix is also converted to lower case and we transform + all not safe character, as we do with MySQL table names. + + If suffix is an empty string, then we don't add any suffix. + This is to allow one to use this function also to generate old + file names without a prefix. +*/ + +void create_logfile_name_with_suffix(char *res_file_name, uint length, + const char *info_file, bool append, + LEX_STRING *suffix) +{ + char buff[MAX_CONNECTION_NAME+1], res[MAX_CONNECTION_NAME+1], *p; + + p= strmake(res_file_name, info_file, length); + /* If not empty suffix and there is place left for some part of the suffix */ + if (suffix->length != 0 && p <= res_file_name + length -1) + { + const char *info_file_end= info_file + (p - res_file_name); + const char *ext= append ? info_file_end : fn_ext2(info_file); + size_t res_length, ext_pos; + uint errors; + + /* Create null terminated string */ + strmake(buff, suffix->str, suffix->length); + /* Convert to lower case */ + my_casedn_str(system_charset_info, buff); + /* Convert to characters usable in a file name */ + res_length= strconvert(system_charset_info, buff, + &my_charset_filename, res, sizeof(res), &errors); + + ext_pos= (size_t) (ext - info_file); + length-= (suffix->length - ext_pos); /* Leave place for extension */ + p= res_file_name + ext_pos; + *p++= '-'; /* Add separator */ + p= strmake(p, res, min(length - (p - res_file_name), res_length)); + /* Add back extension. We have checked above that there is space for it */ + strmov(p, ext); + } +} + + +Master_info_index::Master_info_index() +{ + size_t filename_length, dir_length; + /* + Create the Master_info index file by prepending 'multi-' before + the master_info_file file name. + */ + fn_format(index_file_name, master_info_file, mysql_data_home, + "", MY_UNPACK_FILENAME); + filename_length= strlen(index_file_name) + 1; /* Count 0 byte */ + dir_length= dirname_length(index_file_name); + bmove_upp((uchar*) index_file_name + filename_length + 6, + (uchar*) index_file_name + filename_length, + filename_length - dir_length); + memcpy(index_file_name + dir_length, "multi-", 6); + + bzero((char*) &index_file, sizeof(index_file)); +} + +Master_info_index::~Master_info_index() +{ + /* This will close connection for all objects in the cache */ + my_hash_free(&master_info_hash); + end_io_cache(&index_file); + if (index_file.file > 0) + my_close(index_file.file, MYF(MY_WME)); +} + + +/* Load All Master_info from master.info.index File + * RETURN: + * 0 - All Success + * 1 - All Fail + * 2 - Some Success, Some Fail + */ + +bool Master_info_index::init_all_master_info() +{ + int thread_mask; + int err_num= 0, succ_num= 0; // The number of success read Master_info + char sign[MAX_CONNECTION_NAME]; + File index_file_nr; + DBUG_ENTER("init_all_master_info"); + + if ((index_file_nr= my_open(index_file_name, + O_RDWR | O_CREAT | O_BINARY , + MYF(MY_WME | ME_NOREFRESH))) < 0 || + my_sync(index_file_nr, MYF(MY_WME)) || + init_io_cache(&index_file, index_file_nr, + IO_SIZE, READ_CACHE, + my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)), + 0, MYF(MY_WME | MY_WAIT_IF_FULL))) + { + if (index_file_nr >= 0) + my_close(index_file_nr,MYF(0)); + + sql_print_error("Creation of Master_info index file '%s' failed", + index_file_name); + DBUG_RETURN(1); + } + + /* Initialize Master_info Hash Table */ + if (my_hash_init(&master_info_hash, system_charset_info, + MAX_REPLICATION_THREAD, 0, 0, + (my_hash_get_key) get_key_master_info, + (my_hash_free_key)free_key_master_info, HASH_UNIQUE)) + { + sql_print_error("Initializing Master_info hash table failed"); + DBUG_RETURN(1); + } + + reinit_io_cache(&index_file, READ_CACHE, 0L,0,0); + while (!init_strvar_from_file(sign, sizeof(sign), + &index_file, NULL)) + { + LEX_STRING connection_name; + Master_info *mi; + char buf_master_info_file[FN_REFLEN]; + char buf_relay_log_info_file[FN_REFLEN]; + + connection_name.str= sign; + connection_name.length= strlen(sign); + if (!(mi= new Master_info(&connection_name, relay_log_recovery)) || + mi->error()) + { + delete mi; + DBUG_RETURN(1); + } + + lock_slave_threads(mi); + init_thread_mask(&thread_mask,mi,0 /*not inverse*/); + + create_logfile_name_with_suffix(buf_master_info_file, sizeof(buf_master_info_file), + master_info_file, 0, &connection_name); + create_logfile_name_with_suffix(buf_relay_log_info_file, + sizeof(buf_relay_log_info_file), + relay_log_info_file, 0, &connection_name); + if (global_system_variables.log_warnings > 1) + sql_print_information("Reading Master_info: '%s' Relay_info:'%s'", + buf_master_info_file, buf_relay_log_info_file); + + if (init_master_info(mi, buf_master_info_file, buf_relay_log_info_file, + 0, thread_mask)) + { + err_num++; + sql_print_error("Initialized Master_info from '%s' failed", + buf_master_info_file); + if (!master_info_index->get_master_info(&connection_name, + MYSQL_ERROR::WARN_LEVEL_NOTE)) + { + /* Master_info is not in HASH; Add it */ + if (master_info_index->add_master_info(mi, FALSE)) + return 1; + succ_num++; + unlock_slave_threads(mi); + } + else + { + /* Master_info already in HASH */ + sql_print_error(ER(ER_CONNECTION_ALREADY_EXISTS), + (int) connection_name.length, connection_name.str); + unlock_slave_threads(mi); + delete mi; + } + continue; + } + else + { + /* Initialization of Master_info succeded. Add it to HASH */ + if (global_system_variables.log_warnings > 1) + sql_print_information("Initialized Master_info from '%s'", + buf_master_info_file); + if (master_info_index->get_master_info(&connection_name, + MYSQL_ERROR::WARN_LEVEL_NOTE)) + { + /* Master_info was already registered */ + sql_print_error(ER(ER_CONNECTION_ALREADY_EXISTS), + (int) connection_name.length, connection_name.str); + unlock_slave_threads(mi); + delete mi; + continue; + } + + /* Master_info was not registered; add it */ + if (master_info_index->add_master_info(mi, FALSE)) + return 1; + succ_num++; + unlock_slave_threads(mi); + + if (!opt_skip_slave_start) + { + if (start_slave_threads(1 /* need mutex */, + 0 /* no wait for start*/, + mi, + buf_master_info_file, + buf_relay_log_info_file, + SLAVE_IO | SLAVE_SQL)) + { + sql_print_error("Failed to create slave threads for connection '%.*s'", + (int) connection_name.length, + connection_name.str); + continue; + } + if (global_system_variables.log_warnings) + sql_print_information("Started replication for '%.*s'", + (int) connection_name.length, + connection_name.str); + } + } + } + + if (!err_num) // No Error on read Master_info + { + if (global_system_variables.log_warnings > 1) + sql_print_information("Reading of all Master_info entries succeded"); + DBUG_RETURN(0); + } + else if (succ_num) // Have some Error and some Success + { + sql_print_warning("Reading of some Master_info entries failed"); + DBUG_RETURN(2); + } + else // All failed + { + sql_print_error("Reading of all Master_info entries failed!"); + DBUG_RETURN(1); + } +} + + +/* Write new master.info to master.info.index File */ +bool Master_info_index::write_master_name_to_index_file(LEX_STRING *name, + bool do_sync) +{ + DBUG_ASSERT(my_b_inited(&index_file) != 0); + DBUG_ENTER("write_master_name_to_index_file"); + + /* Don't write default slave to master_info.index */ + if (name->length == 0) + DBUG_RETURN(0); + + reinit_io_cache(&index_file, WRITE_CACHE, + my_b_filelength(&index_file), 0, 0); + + if (my_b_write(&index_file, (uchar*) name->str, name->length) || + my_b_write(&index_file, (uchar*) "\n", 1) || + flush_io_cache(&index_file) || + (do_sync && my_sync(index_file.file, MYF(MY_WME)))) + { + sql_print_error("Write of new Master_info for '%.*s' to index file failed", + (int) name->length, name->str); + DBUG_RETURN(1); + } + + DBUG_RETURN(0); +} + + +/** + Get Master_info for a connection + + @param + connection_name Connection name + warning WARN_LEVEL_NOTE -> Don't print anything + WARN_LEVEL_WARN -> Issue warning if not exists + WARN_LEVEL_ERROR-> Issue error if not exists +*/ + +Master_info * +Master_info_index::get_master_info(LEX_STRING *connection_name, + MYSQL_ERROR::enum_warning_level warning) +{ + Master_info *mi; + char buff[MAX_CONNECTION_NAME+1], *res; + uint buff_length; + DBUG_ENTER("get_master_info"); + DBUG_PRINT("enter", + ("connection_name: '%.*s'", (int) connection_name->length, + connection_name->str)); + + /* Make name lower case for comparison */ + res= strmake(buff, connection_name->str, connection_name->length); + my_casedn_str(system_charset_info, buff); + buff_length= (size_t) (res-buff); + + mi= (Master_info*) my_hash_search(&master_info_hash, + (uchar*) buff, buff_length); + if (!mi && warning != MYSQL_ERROR::WARN_LEVEL_NOTE) + { + my_error(WARN_NO_MASTER_INFO, + MYF(warning == MYSQL_ERROR::WARN_LEVEL_WARN ? ME_JUST_WARNING : + 0), + (int) connection_name->length, + connection_name->str); + } + DBUG_RETURN(mi); +} + + +/* Check Master_host & Master_port is duplicated or not */ +bool Master_info_index::check_duplicate_master_info(LEX_STRING *name_arg, + const char *host, + uint port) +{ + Master_info *mi; + DBUG_ENTER("check_duplicate_master_info"); + + /* Get full host and port name */ + if ((mi= master_info_index->get_master_info(name_arg, + MYSQL_ERROR::WARN_LEVEL_NOTE))) + { + if (!host) + host= mi->host; + if (!port) + port= mi->port; + } + if (!host || !port) + DBUG_RETURN(FALSE); // Not comparable yet + + for (uint i= 0; i < master_info_hash.records; ++i) + { + Master_info *tmp_mi; + tmp_mi= (Master_info *) my_hash_element(&master_info_hash, i); + if (tmp_mi == mi) + continue; // Current connection + if (!strcasecmp(host, tmp_mi->host) && port == tmp_mi->port) + { + my_error(ER_CONNECTION_ALREADY_EXISTS, MYF(0), + (int) name_arg->length, + name_arg->str, + (int) tmp_mi->connection_name.length, + tmp_mi->connection_name.str); + DBUG_RETURN(TRUE); + } + } + DBUG_RETURN(FALSE); +} + + +/* Add a Master_info class to Hash Table */ +bool Master_info_index::add_master_info(Master_info *mi, bool write_to_file) +{ + if (!my_hash_insert(&master_info_hash, (uchar*) mi)) + { + if (global_system_variables.log_warnings > 1) + sql_print_information("Added new Master_info '%.*s' to hash table", + (int) mi->connection_name.length, + mi->connection_name.str); + if (write_to_file) + return write_master_name_to_index_file(&mi->connection_name, 1); + return FALSE; + } + + /* Impossible error (EOM) ? */ + sql_print_error("Adding new entry '%.*s' to master_info failed", + (int) mi->connection_name.length, + mi->connection_name.str); + return TRUE; +} + + +/** + Remove a Master_info class From Hash Table + + TODO: Change this to use my_rename() to make the file name creation + atomic +*/ + +bool Master_info_index::remove_master_info(LEX_STRING *name) +{ + Master_info* mi; + DBUG_ENTER("remove_master_info"); + + if ((mi= get_master_info(name, MYSQL_ERROR::WARN_LEVEL_WARN))) + { + // Delete Master_info and rewrite others to file + if (!my_hash_delete(&master_info_hash, (uchar*) mi)) + { + File index_file_nr; + + // Close IO_CACHE and FILE handler fisrt + end_io_cache(&index_file); + my_close(index_file.file, MYF(MY_WME)); + + // Reopen File and truncate it + if ((index_file_nr= my_open(index_file_name, + O_RDWR | O_CREAT | O_TRUNC | O_BINARY , + MYF(MY_WME))) < 0 || + init_io_cache(&index_file, index_file_nr, + IO_SIZE, WRITE_CACHE, + my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)), + 0, MYF(MY_WME | MY_WAIT_IF_FULL))) + { + int error= my_errno; + if (index_file_nr >= 0) + my_close(index_file_nr,MYF(0)); + + sql_print_error("Create of Master Info Index file '%s' failed with " + "error: %M", + index_file_name, error); + DBUG_RETURN(TRUE); + } + + // Rewrite Master_info.index + for (uint i= 0; i< master_info_hash.records; ++i) + { + Master_info *tmp_mi; + tmp_mi= (Master_info *) my_hash_element(&master_info_hash, i); + write_master_name_to_index_file(&tmp_mi->connection_name, 0); + } + my_sync(index_file_nr, MYF(MY_WME)); + } + } + DBUG_RETURN(FALSE); +} + + +/** + Master_info_index::give_error_if_slave_running() + + @return + TRUE If some slave is running. An error is printed + FALSE No slave is running +*/ + +bool Master_info_index::give_error_if_slave_running() +{ + DBUG_ENTER("warn_if_slave_running"); + mysql_mutex_assert_owner(&LOCK_active_mi); + + for (uint i= 0; i< master_info_hash.records; ++i) + { + Master_info *mi; + mi= (Master_info *) my_hash_element(&master_info_hash, i); + if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN) + { + my_error(ER_SLAVE_MUST_STOP, MYF(0), (int) mi->connection_name.length, + mi->connection_name.str); + DBUG_RETURN(TRUE); + } + } + DBUG_RETURN(FALSE); +} + + +/** + Master_info_index::start_all_slaves() + + Start all slaves that was not running. + + @return + TRUE Error + FALSE Everything ok. +*/ + +bool Master_info_index::start_all_slaves(THD *thd) +{ + bool result= FALSE; + DBUG_ENTER("warn_if_slave_running"); + mysql_mutex_assert_owner(&LOCK_active_mi); + + for (uint i= 0; i< master_info_hash.records; ++i) + { + int error; + Master_info *mi; + mi= (Master_info *) my_hash_element(&master_info_hash, i); + + /* + Try to start all slaves that are configured (host is defined) + and are not already running + */ + if ((mi->slave_running != MYSQL_SLAVE_RUN_CONNECT || + !mi->rli.slave_running) && *mi->host) + { + if ((error= start_slave(thd, mi, 1))) + { + my_error(ER_CANT_START_STOP_SLAVE, MYF(0), + "START", + (int) mi->connection_name.length, + mi->connection_name.str); + result= 1; + if (error < 0) // fatal error + break; + } + else + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_SLAVE_STARTED, ER(ER_SLAVE_STARTED), + (int) mi->connection_name.length, + mi->connection_name.str); + } + } + DBUG_RETURN(result); +} + + +/** + Master_info_index::stop_all_slaves() + + Start all slaves that was not running. + + @return + TRUE Error + FALSE Everything ok. +*/ + +bool Master_info_index::stop_all_slaves(THD *thd) +{ + bool result= FALSE; + DBUG_ENTER("warn_if_slave_running"); + mysql_mutex_assert_owner(&LOCK_active_mi); + + for (uint i= 0; i< master_info_hash.records; ++i) + { + int error; + Master_info *mi; + mi= (Master_info *) my_hash_element(&master_info_hash, i); + if ((mi->slave_running != MYSQL_SLAVE_NOT_RUN || + mi->rli.slave_running)) + { + if ((error= stop_slave(thd, mi, 1))) + { + my_error(ER_CANT_START_STOP_SLAVE, MYF(0), + "STOP", + (int) mi->connection_name.length, + mi->connection_name.str); + result= 1; + if (error < 0) // Fatal error + break; + } + else + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_SLAVE_STOPPED, ER(ER_SLAVE_STOPPED), + (int) mi->connection_name.length, + mi->connection_name.str); + } + } + DBUG_RETURN(result); +} #endif /* HAVE_REPLICATION */ diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index a885576ef1c..48fdd3937c5 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -59,16 +59,23 @@ typedef struct st_mysql MYSQL; class Master_info : public Slave_reporting_capability { public: - Master_info(bool is_slave_recovery); + Master_info(LEX_STRING *connection_name, bool is_slave_recovery); ~Master_info(); bool shall_ignore_server_id(ulong s_id); void clear_in_memory_info(bool all); + bool error() + { + /* If malloc() in initialization failed */ + return connection_name.str == 0; + } /* the variables below are needed because we can change masters on the fly */ - char master_log_name[FN_REFLEN]; + char master_log_name[FN_REFLEN+6]; /* Room for multi-*/ char host[HOSTNAME_LENGTH+1]; char user[USERNAME_LENGTH+1]; char password[MAX_PASSWORD_LENGTH+1]; + LEX_STRING connection_name; /* User supplied connection name */ + LEX_STRING cmp_connection_name; /* Connection name in lower case */ bool ssl; // enables use of SSL connection if true char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN]; char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN]; @@ -130,5 +137,48 @@ int flush_master_info(Master_info* mi, bool need_lock_relay_log); int change_master_server_id_cmp(ulong *id1, ulong *id2); +/* + Multi master are handled trough this struct. + Changes to this needs to be protected by LOCK_active_mi; +*/ + +class Master_info_index +{ +private: + IO_CACHE index_file; + char index_file_name[FN_REFLEN]; + +public: + Master_info_index(); + ~Master_info_index(); + + HASH master_info_hash; + + bool init_all_master_info(); + bool write_master_name_to_index_file(LEX_STRING *connection_name, + bool do_sync); + + bool check_duplicate_master_info(LEX_STRING *connection_name, + const char *host, uint port); + bool add_master_info(Master_info *mi, bool write_to_file); + bool remove_master_info(LEX_STRING *connection_name); + Master_info *get_master_info(LEX_STRING *connection_name, + MYSQL_ERROR::enum_warning_level warning); + bool give_error_if_slave_running(); + bool start_all_slaves(THD *thd); + bool stop_all_slaves(THD *thd); +}; + +bool check_master_connection_name(LEX_STRING *name); +void create_logfile_name_with_suffix(char *res_file_name, uint length, + const char *info_file, + bool append, + LEX_STRING *suffix); + +uchar *get_key_master_info(Master_info *mi, size_t *length, + my_bool not_used __attribute__((unused))); +void free_key_master_info(Master_info *mi); + + #endif /* HAVE_REPLICATION */ #endif /* RPL_MI_H */ diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index a700aff0da9..e74831464fa 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -50,7 +50,7 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery) last_master_timestamp(0), slave_skip_counter(0), abort_pos_wait(0), slave_run_id(0), sql_thd(0), inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE), - until_log_pos(0), retried_trans(0), + until_log_pos(0), retried_trans(0), executed_entries(0), tables_to_lock(0), tables_to_lock_count(0), last_event_start_time(0), deferred_events(NULL),m_flags(0), row_stmt_start_timestamp(0), long_find_row_note_printed(false), @@ -69,6 +69,7 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery) group_relay_log_name[0]= event_relay_log_name[0]= group_master_log_name[0]= 0; until_log_name[0]= ign_master_log_name_end[0]= 0; + max_relay_log_size= global_system_variables.max_relay_log_size; bzero((char*) &info_file, sizeof(info_file)); bzero((char*) &cache_buf, sizeof(cache_buf)); cached_charset_invalidate(); @@ -149,15 +150,6 @@ int init_relay_log_info(Relay_log_info* rli, event, in flush_master_info(mi, 1, ?). */ - /* - For the maximum log size, we choose max_relay_log_size if it is - non-zero, max_binlog_size otherwise. If later the user does SET - GLOBAL on one of these variables, fix_max_binlog_size and - fix_max_relay_log_size will reconsider the choice (for example - if the user changes max_relay_log_size to zero, we have to - switch to using max_binlog_size for the relay log) and update - rli->relay_log.max_size (and mysql_bin_log.max_size). - */ { /* Reports an error and returns, if the --relay-log's path is a directory.*/ @@ -206,19 +198,36 @@ a file name for --relay-log-index option", opt_relaylog_index_name); name_warning_sent= 1; } + /* For multimaster, add connection name to relay log filenames */ + Master_info* mi= rli->mi; + char buf_relay_logname[FN_REFLEN], buf_relaylog_index_name_buff[FN_REFLEN]; + char *buf_relaylog_index_name= opt_relaylog_index_name; + + create_logfile_name_with_suffix(buf_relay_logname, sizeof(buf_relay_logname), + ln, 1, &mi->connection_name); + ln= buf_relay_logname; + + if (opt_relaylog_index_name) + { + buf_relaylog_index_name= buf_relaylog_index_name_buff; + create_logfile_name_with_suffix(buf_relaylog_index_name_buff, + sizeof(buf_relaylog_index_name_buff), + opt_relaylog_index_name, 0, + &mi->connection_name); + } + rli->relay_log.is_relay_log= TRUE; /* note, that if open() fails, we'll still have index file open but a destructor will take care of that */ - if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln, TRUE) || + if (rli->relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) || rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, - (max_relay_log_size ? max_relay_log_size : - max_binlog_size), 1, TRUE)) + mi->rli.max_relay_log_size, 1, TRUE)) { mysql_mutex_unlock(&rli->data_lock); - sql_print_error("Failed in open_log() called from init_relay_log_info()"); + sql_print_error("Failed when trying to open logs for '%s' in init_relay_log_info(). Error: %M", ln, my_errno); DBUG_RETURN(1); } } @@ -997,28 +1006,37 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, rli->cur_log_fd= -1; } - if (rli->relay_log.reset_logs(thd)) + if (rli->relay_log.reset_logs(thd, !just_reset)) { *errmsg = "Failed during log reset"; error=1; goto err; } - /* Save name of used relay log file */ - strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(), - sizeof(rli->group_relay_log_name)-1); - strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(), - sizeof(rli->event_relay_log_name)-1); - rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE; - if (count_relay_log_space(rli)) - { - *errmsg= "Error counting relay log space"; - error=1; - goto err; - } if (!just_reset) + { + /* Save name of used relay log file */ + strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(), + sizeof(rli->group_relay_log_name)-1); + strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(), + sizeof(rli->event_relay_log_name)-1); + rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE; + rli->log_space_total= 0; + + if (count_relay_log_space(rli)) + { + *errmsg= "Error counting relay log space"; + error=1; + goto err; + } error= init_relay_log_pos(rli, rli->group_relay_log_name, rli->group_relay_log_pos, 0 /* do not need data lock */, errmsg, 0); + } + else + { + /* Ensure relay log names are not used */ + rli->group_relay_log_name[0]= rli->event_relay_log_name[0]= 0; + } err: #ifndef DBUG_OFF diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index b989283deb4..6144d37026b 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -25,7 +25,6 @@ struct RPL_TABLE_LIST; class Master_info; -extern uint sql_slave_skip_counter; /**************************************************************************** @@ -229,10 +228,12 @@ public: Needed for problems when slave stops and we want to restart it skipping one or more events in the master log that have caused errors, and have been manually applied by DBA already. + Must be ulong as it's refered to from set_var.cc */ - volatile uint32 slave_skip_counter; + volatile ulong slave_skip_counter; volatile ulong abort_pos_wait; /* Incremented on change master */ volatile ulong slave_run_id; /* Incremented on slave start */ + ulong max_relay_log_size; mysql_mutex_t log_space_lock; mysql_cond_t log_space_cond; THD * sql_thd; @@ -286,6 +287,7 @@ public: slave started. */ ulong trans_retries, retried_trans; + ulong executed_entries; /* For SLAVE STATUS */ /* If the end of the hot relay log is made of master's events ignored by the diff --git a/sql/set_var.cc b/sql/set_var.cc index 8e2f90b9bfd..43aa10fbebd 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -263,7 +263,7 @@ uchar *sys_var::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) bool sys_var::set_default(THD *thd, enum_var_type type) { LEX_STRING empty={0,0}; - set_var var(type, 0, &empty, 0); + set_var var(type, this, &empty, 0); if (type == OPT_GLOBAL || scope() == GLOBAL) global_save_default(thd, &var); diff --git a/sql/set_var.h b/sql/set_var.h index 6edfd6adb39..fea947aa1da 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -68,13 +68,14 @@ public: enum binlog_status_enum { VARIABLE_NOT_IN_BINLOG, SESSION_VARIABLE_IN_BINLOG } binlog_status; + my_option option; ///< min, max, default values are stored here + protected: typedef bool (*on_check_function)(sys_var *self, THD *thd, set_var *var); typedef bool (*on_update_function)(sys_var *self, THD *thd, enum_var_type type); int flags; ///< or'ed flag_enum values const SHOW_TYPE show_val_type; ///< what value_ptr() returns for sql_show.cc - my_option option; ///< min, max, default values are stored here PolyLock *guard; ///< *second* lock that protects the variable ptrdiff_t offset; ///< offset to the value from global_system_variables on_check_function on_check; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 2e8b2231948..3832ee150e3 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -4271,18 +4271,18 @@ ER_TRANS_CACHE_FULL swe "Transaktionen krävde mera än 'max_binlog_cache_size' minne. Öka denna mysqld-variabel och försök på nytt" ukr "Транзакція з багатьма виразами вимагає більше ніж 'max_binlog_cache_size' байтів для зберігання. Збільште цю змінну mysqld та спробуйте знову" ER_SLAVE_MUST_STOP - dan "Denne handling kunne ikke udføres med kørende slave, brug først kommandoen STOP SLAVE" - nla "Deze operatie kan niet worden uitgevoerd met een actieve slave, doe eerst STOP SLAVE" - eng "This operation cannot be performed with a running slave; run STOP SLAVE first" - fre "Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord" - ger "Diese Operation kann bei einem aktiven Slave nicht durchgeführt werden. Bitte zuerst STOP SLAVE ausführen" - ita "Questa operazione non puo' essere eseguita con un database 'slave' che gira, lanciare prima STOP SLAVE" - por "Esta operação não pode ser realizada com um 'slave' em execução. Execute STOP SLAVE primeiro" - rus "Эту операцию невозможно выполнить при работающем потоке подчиненного сервера. Сначала выполните STOP SLAVE" - serbian "Ova operacija ne može biti izvršena dok je aktivan podređeni server. Zadajte prvo komandu 'STOP SLAVE' da zaustavite podređeni server." - spa "Esta operación no puede ser hecha con el esclavo funcionando, primero use STOP SLAVE" - swe "Denna operation kan inte göras under replikering; Gör STOP SLAVE först" - ukr "Операція не може бути виконана з запущеним підлеглим, спочатку виконайте STOP SLAVE" + dan "Denne handling kunne ikke udføres med kørende slave '%2$*1$s', brug først kommandoen STOP SLAVE '%2$*1$s'" + nla "Deze operatie kan niet worden uitgevoerd met een actieve slave '%2$*1$s', doe eerst STOP SLAVE '%2$*1$s'" + eng "This operation cannot be performed as you have a running slave '%2$*1$s'; run STOP SLAVE '%2$*1$s' first" + fre "Cette opération ne peut être réalisée avec un esclave '%2$*1$s' actif, faites STOP SLAVE '%2$*1$s' d'abord" + ger "Diese Operation kann bei einem aktiven Slave '%2$*1$s' nicht durchgeführt werden. Bitte zuerst STOP SLAVE '%2$*1$s' ausführen" + ita "Questa operazione non puo' essere eseguita con un database 'slave' '%2$*1$s' che gira, lanciare prima STOP SLAVE '%2$*1$s'" + por "Esta operação não pode ser realizada com um 'slave' '%2$*1$s' em execução. Execute STOP SLAVE '%2$*1$s' primeiro" + rus "Эту операцию невозможно выполнить при работающем потоке подчиненного сервера %2$*1$s. Сначала выполните STOP SLAVE '%2$*1$s'" + serbian "Ova operacija ne može biti izvršena dok je aktivan podređeni '%2$*1$s' server. Zadajte prvo komandu 'STOP SLAVE '%2$*1$s'' da zaustavite podređeni server." + spa "Esta operación no puede ser hecha con el esclavo '%2$*1$s' funcionando, primero use STOP SLAVE '%2$*1$s'" + swe "Denna operation kan inte göras under replikering; Du har en aktiv förbindelse till '%2$*1$s'. Gör STOP SLAVE '%2$*1$s' först" + ukr "Операція не може бути виконана з запущеним підлеглим '%2$*1$s', спочатку виконайте STOP SLAVE '%2$*1$s'" ER_SLAVE_NOT_RUNNING dan "Denne handling kræver en kørende slave. Konfigurer en slave og brug kommandoen START SLAVE" nla "Deze operatie vereist een actieve slave, configureer slave en doe dan START SLAVE" @@ -4310,11 +4310,11 @@ ER_BAD_SLAVE swe "Servern är inte konfigurerade som en replikationsslav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO" ukr "Сервер не зконфігуровано як підлеглий, виправте це у файлі конфігурації або з CHANGE MASTER TO" ER_MASTER_INFO - eng "Could not initialize master info structure; more error messages can be found in the MariaDB error log" - fre "Impossible d'initialiser les structures d'information de maître, vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MariaDB" - ger "Konnte Master-Info-Struktur nicht initialisieren. Weitere Fehlermeldungen können im MariaDB-Error-Log eingesehen werden" - serbian "Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info'" - swe "Kunde inte initialisera replikationsstrukturerna. See MariaDB fel fil för mera information" + eng "Could not initialize master info structure for '%.*s'; more error messages can be found in the MariaDB error log" + fre "Impossible d'initialiser les structures d'information de maître '%.*s', vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MariaDB" + ger "Konnte Master-Info-Struktur '%.*s' nicht initialisieren. Weitere Fehlermeldungen können im MariaDB-Error-Log eingesehen werden" + serbian "Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info' '%.*s'" + swe "Kunde inte initialisera replikationsstrukturerna för '%.*s'. See MariaDB fel fil för mera information" ER_SLAVE_THREAD dan "Kunne ikke danne en slave-tråd; check systemressourcerne" nla "Kon slave thread niet aanmaken, controleer systeem resources" @@ -6156,8 +6156,8 @@ ER_DELAYED_NOT_SUPPORTED eng "DELAYED option not supported for table '%-.192s'" ger "Die DELAYED-Option wird für Tabelle '%-.192s' nicht unterstützt" WARN_NO_MASTER_INFO - eng "The master info structure does not exist" - ger "Die Master-Info-Struktur existiert nicht" + eng "There is no master connection '%.*s'" + ger "Die Master-Info-Struktur existiert nicht '%.*s'" WARN_OPTION_IGNORED eng "<%-.64s> option ignored" ger "Option <%-.64s> ignoriert" @@ -6588,3 +6588,13 @@ ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT ER_NO_SUCH_TABLE_IN_ENGINE 42S02 eng "Table '%-.192s.%-.192s' doesn't exist in engine" swe "Det finns ingen tabell som heter '%-.192s.%-.192s' i handlern" +ER_CONNECTION_ALREADY_EXISTS + eng "Connection '%.*s' conflicts with existing connection '%.*s'" +ER_MASTER_LOG_PREFIX + eng "Master '%.*s': " +ER_CANT_START_STOP_SLAVE + eng "Can't %s SLAVE '%.*s'" +ER_SLAVE_STARTED + eng "SLAVE '%.*s' started" +ER_SLAVE_STOPPED + eng "SLAVE '%.*s' stopped" diff --git a/sql/slave.cc b/sql/slave.cc index 7b7bddecd17..b4dee4d64a7 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -71,8 +71,10 @@ char slave_skip_error_names[SHOW_VAR_FUNC_BUFF_SIZE]; char* slave_load_tmpdir = 0; Master_info *active_mi= 0; +Master_info_index *master_info_index; my_bool replicate_same_server_id; ulonglong relay_log_space_limit = 0; +LEX_STRING default_master_connection_name= { (char*) "", 0 }; /* When slave thread exits, we need to remember the temporary tables so we @@ -144,7 +146,8 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev); static bool wait_for_relay_log_space(Relay_log_info* rli); static inline bool io_slave_killed(THD* thd,Master_info* mi); static inline bool sql_slave_killed(THD* thd,Relay_log_info* rli); -static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type); +static int init_slave_thread(THD* thd, Master_info *mi, + SLAVE_THD_TYPE thd_type); static void print_slave_skip_errors(void); static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi); static int safe_reconnect(THD* thd, MYSQL* mysql, Master_info* mi, @@ -159,6 +162,8 @@ static int terminate_slave_thread(THD *thd, volatile uint *slave_running, bool skip_lock); static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info); +static bool send_show_master_info_header(THD *thd, bool full); +static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full); /* Find out which replications threads are running @@ -263,15 +268,33 @@ int init_slave() So it's safer to take the lock. */ mysql_mutex_lock(&LOCK_active_mi); - /* - TODO: re-write this to interate through the list of files - for multi-master - */ - active_mi= new Master_info(relay_log_recovery); if (pthread_key_create(&RPL_MASTER_INFO, NULL)) goto err; + master_info_index= new Master_info_index; + if (!master_info_index || master_info_index->init_all_master_info()) + { + sql_print_error("Failed to initialize multi master structures"); + mysql_mutex_unlock(&LOCK_active_mi); + DBUG_RETURN(1); + } + if (!(active_mi= new Master_info(&default_master_connection_name, + relay_log_recovery)) || + active_mi->error()) + { + delete active_mi; + active_mi= 0; + goto err; + } + + if (master_info_index->add_master_info(active_mi, FALSE)) + { + delete active_mi; + active_mi= 0; + goto err; + } + /* If --slave-skip-errors=... was not used, the string value for the system variable has not been set up yet. Do it now. @@ -286,18 +309,11 @@ int init_slave() If master_host is specified, create the master_info file if it doesn't exists. */ - if (!active_mi) - { - sql_print_error("Failed to allocate memory for the master info structure"); - error= 1; - goto err; - } if (init_master_info(active_mi,master_info_file,relay_log_info_file, 1, (SLAVE_IO | SLAVE_SQL))) { sql_print_error("Failed to initialize the master info structure"); - error= 1; goto err; } @@ -313,14 +329,18 @@ int init_slave() SLAVE_IO | SLAVE_SQL)) { sql_print_error("Failed to create slave threads"); - error= 1; goto err; } } -err: +end: mysql_mutex_unlock(&LOCK_active_mi); DBUG_RETURN(error); + +err: + sql_print_error("Failed to allocate memory for the Master Info structure"); + error= 1; + goto end; } /* @@ -820,42 +840,19 @@ void end_slave() running presently. If a START SLAVE was in progress, the mutex lock below will make us wait until slave threads have started, and START SLAVE returns, then we terminate them here. + + We can also be called by cleanup(), which only happens if some + startup parameter to the server was wrong. */ mysql_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - /* - TODO: replace the line below with - list_walk(&master_list, (list_walk_action)end_slave_on_walk,0); - once multi-master code is ready. - */ - terminate_slave_threads(active_mi,SLAVE_FORCE_ALL); - } + /* This will call terminate_slave_threads() on all connections */ + delete master_info_index; + master_info_index= 0; + active_mi= 0; mysql_mutex_unlock(&LOCK_active_mi); DBUG_VOID_RETURN; } -/** - Free all resources used by slave threads at time of executing shutdown. - The routine must be called after all possible users of @c active_mi - have left. - - SYNOPSIS - close_active_mi() - -*/ -void close_active_mi() -{ - mysql_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - end_master_info(active_mi); - delete active_mi; - active_mi= 0; - } - mysql_mutex_unlock(&LOCK_active_mi); -} - static bool io_slave_killed(THD* thd, Master_info* mi) { DBUG_ENTER("io_slave_killed"); @@ -1866,9 +1863,9 @@ Waiting for the slave SQL thread to free enough relay log space"); #endif if (rli->sql_force_rotate_relay) { - mysql_mutex_lock(&active_mi->data_lock); + mysql_mutex_lock(&mi->data_lock); rotate_relay_log(rli->mi); - mysql_mutex_unlock(&active_mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); rli->sql_force_rotate_relay= false; } @@ -2022,15 +2019,36 @@ int register_slave_on_master(MYSQL* mysql, Master_info *mi, @retval FALSE success @retval TRUE failure */ -bool show_master_info(THD* thd, Master_info* mi) + +bool show_master_info(THD *thd, Master_info *mi, bool full) +{ + DBUG_ENTER("show_master_info"); + + if (send_show_master_info_header(thd, full)) + DBUG_RETURN(TRUE); + if (send_show_master_info_data(thd, mi, full)) + DBUG_RETURN(TRUE); + my_eof(thd); + DBUG_RETURN(FALSE); +} + +static bool send_show_master_info_header(THD *thd, bool full) { - // TODO: fix this for multi-master List<Item> field_list; Protocol *protocol= thd->protocol; - DBUG_ENTER("show_master_info"); + Master_info *mi; + DBUG_ENTER("show_master_info_header"); + + if (full) + { + field_list.push_back(new Item_empty_string("Connection_name", + MAX_CONNECTION_NAME)); + field_list.push_back(new Item_empty_string("Slave_SQL_State", + 30)); + } field_list.push_back(new Item_empty_string("Slave_IO_State", - 14)); + 30)); field_list.push_back(new Item_empty_string("Master_Host", sizeof(mi->host))); field_list.push_back(new Item_empty_string("Master_User", @@ -2093,22 +2111,51 @@ bool show_master_info(THD* thd, Master_info* mi) FN_REFLEN)); field_list.push_back(new Item_return_int("Master_Server_Id", sizeof(ulong), MYSQL_TYPE_LONG)); - + if (full) + { + field_list.push_back(new Item_return_int("Retried_transactions", + 10, MYSQL_TYPE_LONG)); + field_list.push_back(new Item_return_int("Max_relay_log_size", + 10, MYSQL_TYPE_LONGLONG)); + field_list.push_back(new Item_return_int("Executed_log_entries", + 10, MYSQL_TYPE_LONG)); + field_list.push_back(new Item_return_int("Slave_received_heartbeats", + 10, MYSQL_TYPE_LONG)); + field_list.push_back(new Item_float("Slave_heartbeat_period", + 0.0, 3, 10)); + } if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); + DBUG_RETURN(FALSE); +} + + +static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full) +{ + DBUG_ENTER("send_show_master_info_data"); if (mi->host[0]) { DBUG_PRINT("info",("host is set: '%s'", mi->host)); String *packet= &thd->packet; + Protocol *protocol= thd->protocol; + char buf[256]; + String tmp(buf, sizeof(buf), &my_charset_bin); + protocol->prepare_for_resend(); /* slave_running can be accessed without run_lock but not other non-volotile members like mi->io_thd, which is guarded by the mutex. */ + if (full) + protocol->store(mi->connection_name.str, mi->connection_name.length, + &my_charset_bin); mysql_mutex_lock(&mi->run_lock); + if (full) + protocol->store(mi->rli.sql_thd ? mi->rli.sql_thd->proc_info : "", + &my_charset_bin); protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin); mysql_mutex_unlock(&mi->run_lock); @@ -2134,8 +2181,6 @@ bool show_master_info(THD* thd, Master_info* mi) protocol->store(rpl_filter->get_do_db()); protocol->store(rpl_filter->get_ignore_db()); - char buf[256]; - String tmp(buf, sizeof(buf), &my_charset_bin); rpl_filter->get_do_table(&tmp); protocol->store(&tmp); rpl_filter->get_ignore_table(&tmp); @@ -2241,6 +2286,14 @@ bool show_master_info(THD* thd, Master_info* mi) } // Master_Server_id protocol->store((uint32) mi->master_id); + if (full) + { + protocol->store((uint32) mi->rli.retried_trans); + protocol->store((ulonglong) mi->rli.max_relay_log_size); + protocol->store((uint32) mi->rli.executed_entries); + protocol->store((uint32) mi->received_heartbeats); + protocol->store((double) mi->heartbeat_period, 3, &tmp); + } mysql_mutex_unlock(&mi->rli.err_lock); mysql_mutex_unlock(&mi->err_lock); @@ -2250,6 +2303,69 @@ bool show_master_info(THD* thd, Master_info* mi) if (my_net_write(&thd->net, (uchar*) thd->packet.ptr(), packet->length())) DBUG_RETURN(TRUE); } + DBUG_RETURN(FALSE); +} + + +/* Used to sort connections by name */ + +static int cmp_mi_by_name(const Master_info **arg1, + const Master_info **arg2) +{ + return my_strcasecmp(system_charset_info, (*arg1)->connection_name.str, + (*arg2)->connection_name.str); +} + + +/** + Execute a SHOW FULL SLAVE STATUS statement. + + @param thd Pointer to THD object for the client thread executing the + statement. + + Elements are sorted according to the original connection_name. + + @retval FALSE success + @retval TRUE failure + + @note + master_info_index is protected by LOCK_active_mi. +*/ + +bool show_all_master_info(THD* thd) +{ + uint i, elements; + Master_info **tmp; + DBUG_ENTER("show_master_info"); + mysql_mutex_assert_owner(&LOCK_active_mi); + + if (send_show_master_info_header(thd, 1)) + DBUG_RETURN(TRUE); + + if (!(elements= master_info_index->master_info_hash.records)) + goto end; + + /* + Sort lines to get them into a predicted order + (needed for test cases and to not confuse users) + */ + if (!(tmp= (Master_info**) thd->alloc(sizeof(Master_info*) * elements))) + DBUG_RETURN(TRUE); + + for (i= 0; i < elements; i++) + { + tmp[i]= (Master_info *) my_hash_element(&master_info_index-> + master_info_hash, i); + } + my_qsort(tmp, elements, sizeof(Master_info*), (qsort_cmp) cmp_mi_by_name); + + for (i= 0; i < elements; i++) + { + if (send_show_master_info_data(thd, tmp[i], 1)) + DBUG_RETURN(TRUE); + } + +end: my_eof(thd); DBUG_RETURN(FALSE); } @@ -2303,7 +2419,8 @@ void set_slave_thread_default_charset(THD* thd, Relay_log_info const *rli) init_slave_thread() */ -static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) +static int init_slave_thread(THD* thd, Master_info *mi, + SLAVE_THD_TYPE thd_type) { DBUG_ENTER("init_slave_thread"); #if !defined(DBUG_OFF) @@ -2319,7 +2436,8 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) than the corresponding packet (query) sent from client to master. */ thd->variables.max_allowed_packet= slave_max_allowed_packet; - thd->slave_thread = 1; + thd->slave_thread= 1; + thd->connection_name= mi->connection_name; thd->enable_slow_log= opt_log_slow_slave_statements; thd->variables.log_slow_filter= global_system_variables.log_slow_filter; set_slave_thread_options(thd); @@ -2635,7 +2753,10 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) int reason= ev->shall_skip(rli); if (reason == Log_event::EVENT_SKIP_COUNT) - sql_slave_skip_counter= --rli->slave_skip_counter; + { + DBUG_ASSERT(rli->slave_skip_counter > 0); + rli->slave_skip_counter--; + } mysql_mutex_unlock(&rli->data_lock); if (reason == Log_event::EVENT_SKIP_NOT) exec_res= ev->apply_event(rli); @@ -2884,6 +3005,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) mysql_mutex_lock(&rli->data_lock); // because of SHOW STATUS rli->trans_retries++; rli->retried_trans++; + statistic_increment(slave_retried_transactions, LOCK_status); mysql_mutex_unlock(&rli->data_lock); DBUG_PRINT("info", ("Slave retries transaction " "rli->trans_retries: %lu", rli->trans_retries)); @@ -3058,7 +3180,7 @@ pthread_handler_t handle_slave_io(void *arg) pthread_detach_this_thread(); thd->thread_stack= (char*) &thd; // remember where our stack is mi->clear_error(); - if (init_slave_thread(thd, SLAVE_THD_IO)) + if (init_slave_thread(thd, mi, SLAVE_THD_IO)) { mysql_cond_broadcast(&mi->start_cond); sql_print_error("Failed during slave I/O thread initialization"); @@ -3067,7 +3189,7 @@ pthread_handler_t handle_slave_io(void *arg) mysql_mutex_lock(&LOCK_thread_count); threads.append(thd); mysql_mutex_unlock(&LOCK_thread_count); - mi->slave_running = 1; + mi->slave_running = MYSQL_SLAVE_RUN_NOT_CONNECT; mi->abort_slave = 0; mysql_mutex_unlock(&mi->run_lock); mysql_cond_broadcast(&mi->start_cond); @@ -3379,7 +3501,7 @@ err_during_init: delete thd; mysql_mutex_unlock(&LOCK_thread_count); mi->abort_slave= 0; - mi->slave_running= 0; + mi->slave_running= MYSQL_SLAVE_NOT_RUN; mi->io_thd= 0; /* Note: the order of the two following calls (first broadcast, then unlock) @@ -3457,7 +3579,8 @@ pthread_handler_t handle_slave_sql(void *arg) my_off_t UNINIT_VAR(saved_log_pos); my_off_t UNINIT_VAR(saved_master_log_pos); my_off_t saved_skip= 0; - Relay_log_info* rli = &((Master_info*)arg)->rli; + Master_info *mi= ((Master_info*)arg); + Relay_log_info* rli = &mi->rli; const char *errmsg; // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff @@ -3471,6 +3594,7 @@ pthread_handler_t handle_slave_sql(void *arg) thd->thread_stack = (char*)&thd; // remember where our stack is DBUG_ASSERT(rli->inited); + DBUG_ASSERT(rli->mi == mi); mysql_mutex_lock(&rli->run_lock); DBUG_ASSERT(!rli->slave_running); errmsg= 0; @@ -3482,10 +3606,10 @@ pthread_handler_t handle_slave_sql(void *arg) /* Inform waiting threads that slave has started */ rli->slave_run_id++; - rli->slave_running = 1; + rli->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT; pthread_detach_this_thread(); - if (init_slave_thread(thd, SLAVE_THD_SQL)) + if (init_slave_thread(thd, mi, SLAVE_THD_SQL)) { /* TODO: this is currently broken - slave start and change master @@ -3726,6 +3850,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ } goto err; } + rli->executed_entries++; } /* Thread stopped. Print the current replication position to the log */ @@ -3756,9 +3881,9 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ err_during_init: /* We need data_lock, at least to wake up any waiting master_pos_wait() */ mysql_mutex_lock(&rli->data_lock); - DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun + DBUG_ASSERT(rli->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT); // tracking buffer overrun /* When master_pos_wait() wakes up it will check this and terminate */ - rli->slave_running= 0; + rli->slave_running= MYSQL_SLAVE_NOT_RUN; /* Forget the relay log's format */ delete rli->relay_log.description_event_for_exec; rli->relay_log.description_event_for_exec= 0; @@ -5273,11 +5398,6 @@ static Log_event* next_event(Relay_log_info* rli) mysql_mutex_lock(log_lock); if (rli->relay_log.is_active(rli->linfo.log_file_name)) { -#ifdef EXTRA_DEBUG - if (global_system_variables.log_warnings) - sql_print_information("next log '%s' is currently active", - rli->linfo.log_file_name); -#endif rli->cur_log= cur_log= rli->relay_log.get_log_file(); rli->cur_log_old_open_count= rli->relay_log.get_open_count(); DBUG_ASSERT(rli->cur_log_fd == -1); @@ -5360,11 +5480,6 @@ static Log_event* next_event(Relay_log_info* rli) ourselves. We are sure that the log is still not hot now (a log can get from hot to cold, but not from cold to hot). No need for LOCK_log. */ -#ifdef EXTRA_DEBUG - if (global_system_variables.log_warnings) - sql_print_information("next log '%s' is not active", - rli->linfo.log_file_name); -#endif // open_binlog() will check the magic header if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name, &errmsg)) <0) @@ -5544,11 +5659,10 @@ bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, */ bool rpl_master_erroneous_autoinc(THD *thd) { - if (active_mi && active_mi->rli.sql_thd == thd) + if (thd->rli_slave) { - Relay_log_info *rli= &active_mi->rli; DBUG_EXECUTE_IF("simulate_bug33029", return TRUE;); - return rpl_master_has_bug(rli, 33029, FALSE, NULL, NULL); + return rpl_master_has_bug(thd->rli_slave, 33029, FALSE, NULL, NULL); } return FALSE; } diff --git a/sql/slave.h b/sql/slave.h index 6b4bcffe109..565f40b7236 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -45,9 +45,12 @@ #define MAX_SLAVE_ERROR 2000 +#define MAX_REPLICATION_THREAD 64 + // Forward declarations class Relay_log_info; class Master_info; +class Master_info_index; int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, @@ -197,7 +200,8 @@ int mysql_table_dump(THD* thd, const char* db, int fetch_master_table(THD* thd, const char* db_name, const char* table_name, Master_info* mi, MYSQL* mysql, bool overwrite); -bool show_master_info(THD* thd, Master_info* mi); +bool show_master_info(THD* thd, Master_info* mi, bool full); +bool show_all_master_info(THD* thd); bool show_binlog_info(THD* thd); bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, bool (*pred)(const void *), const void *param); @@ -231,6 +235,9 @@ bool net_request_file(NET* net, const char* fname); extern bool volatile abort_loop; extern Master_info main_mi, *active_mi; /* active_mi for multi-master */ +extern Master_info *default_master_info; /* To replace active_mi */ +extern Master_info_index *master_info_index; +extern LEX_STRING default_master_connection_name; extern LIST master_list; extern my_bool replicate_same_server_id; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 85e9227c154..c098ba5be7c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -396,6 +396,7 @@ bool table_def_init(void) void table_def_start_shutdown(void) { + DBUG_ENTER("table_def_start_shutdown"); if (table_def_inited) { mysql_mutex_lock(&LOCK_open); @@ -410,6 +411,7 @@ void table_def_start_shutdown(void) /* Free all cached but unused TABLEs and TABLE_SHAREs. */ close_cached_tables(NULL, NULL, FALSE, LONG_TIMEOUT); } + DBUG_VOID_RETURN; } @@ -1086,6 +1088,9 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, mysql_mutex_unlock(&LOCK_open); + DBUG_PRINT("info", ("open table definitions: %d", + (int) table_def_cache.records)); + if (!wait_for_refresh) DBUG_RETURN(result); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f77ef114d2d..b0d262f7b6a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -799,6 +799,9 @@ THD::THD() progress.max_counter= 0; current_linfo = 0; slave_thread = 0; + connection_name.str= 0; + connection_name.length= 0; + bzero(&variables, sizeof(variables)); thread_id= 0; one_shot_set= 0; @@ -1166,7 +1169,14 @@ void THD::init(void) avoid temporary tables replication failure. */ variables.pseudo_thread_id= thread_id; + + variables.default_master_connection.str= default_master_connection_buff; + ::strmake(variables.default_master_connection.str, + global_system_variables.default_master_connection.str, + variables.default_master_connection.length); + mysql_mutex_unlock(&LOCK_global_system_variables); + server_status= SERVER_STATUS_AUTOCOMMIT; if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; diff --git a/sql/sql_class.h b/sql/sql_class.h index 3aa0c5ae9c7..dd203af2a1b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -533,6 +533,12 @@ typedef struct system_variables thread the query is being run to replicate temp tables properly */ my_thread_id pseudo_thread_id; + /** + Place holders to store Multi-source variables in sys_var.cc during + update and show of variables. + */ + ulong slave_skip_counter; + ulong max_relay_log_size; my_bool low_priority_updates; my_bool query_cache_wlock_invalidate; @@ -557,6 +563,9 @@ typedef struct system_variables CHARSET_INFO *collation_database; CHARSET_INFO *collation_connection; + /* Names. These will be allocated in buffers in thd */ + LEX_STRING default_master_connection; + /* Error messages */ MY_LOCALE *lc_messages; /* Locale Support */ @@ -2192,6 +2201,12 @@ public: /* scramble - random string sent to client on handshake */ char scramble[SCRAMBLE_LENGTH+1]; + /* + If this is a slave, the name of the connection stored here. + This is used for taging error messages in the log files. + */ + LEX_STRING connection_name; + char default_master_connection_buff[MAX_CONNECTION_NAME+1]; bool slave_thread, one_shot_set; bool extra_port; /* If extra connection */ diff --git a/sql/sql_const.h b/sql/sql_const.h index cfbf077bd91..255a0162e93 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -38,6 +38,7 @@ #define MAX_REFLENGTH 4 /* Max length for record ref */ #endif #define MAX_HOSTNAME 61 /* len+1 in mysql.user */ +#define MAX_CONNECTION_NAME NAME_LEN #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FIELD_CHARLENGTH 255 diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3c3b9f85727..4372f6dfbfe 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -850,10 +850,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, table->next_number_field=table->found_next_number_field; #ifdef HAVE_REPLICATION - if (thd->slave_thread && + if (thd->rli_slave && (info.handle_duplicates == DUP_UPDATE) && (table->next_number_field != NULL) && - rpl_master_has_bug(&active_mi->rli, 24432, TRUE, NULL, NULL)) + rpl_master_has_bug(thd->rli_slave, 24432, TRUE, NULL, NULL)) goto abort; #endif @@ -3436,10 +3436,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) table->next_number_field=table->found_next_number_field; #ifdef HAVE_REPLICATION - if (thd->slave_thread && + if (thd->rli_slave && (info.handle_duplicates == DUP_UPDATE) && (table->next_number_field != NULL) && - rpl_master_has_bug(&active_mi->rli, 24432, TRUE, NULL, NULL)) + rpl_master_has_bug(thd->rli_slave, 24432, TRUE, NULL, NULL)) DBUG_RETURN(1); #endif diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 240aeb223d4..0b8265e7028 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -503,6 +503,7 @@ void lex_start(THD *thd) lex->expr_allows_subselect= TRUE; lex->use_only_table_context= FALSE; lex->parse_vcol_expr= FALSE; + lex->verbose= 0; lex->name.str= 0; lex->name.length= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 2f3214646de..ddac6fc349b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -156,7 +156,8 @@ enum enum_sql_command { SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT, SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT, - SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, + SQLCOM_SLAVE_START, SQLCOM_SLAVE_ALL_START, + SQLCOM_SLAVE_STOP, SQLCOM_SLAVE_ALL_STOP, SQLCOM_BEGIN, SQLCOM_CHANGE_MASTER, SQLCOM_RENAME_TABLE, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS, @@ -286,6 +287,7 @@ struct LEX_MASTER_INFO char *host, *user, *password, *log_file_name; char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher; char *relay_log_name; + LEX_STRING connection_name; ulonglong pos; ulong relay_log_pos; ulong server_id; @@ -2416,6 +2418,7 @@ struct LEX: public Query_tables_list KEY_CREATE_INFO key_create_info; LEX_MASTER_INFO mi; // used by CHANGE MASTER LEX_SERVER_OPTIONS server_options; + LEX_STRING relay_log_connection_name; USER_RESOURCES mqh; LEX_RESET_SLAVE reset_slave_info; ulong type; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 98031c96225..e2c744401b9 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -375,11 +375,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, MY_RETURN_REAL_PATH); } - if (thd->slave_thread) + if (thd->rli_slave) { #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) - if (strncmp(active_mi->rli.slave_patternload_file, name, - active_mi->rli.slave_patternload_file_size)) + if (strncmp(thd->rli_slave->slave_patternload_file, name, + thd->rli_slave->slave_patternload_file_size)) { /* LOAD DATA INFILE in the slave SQL Thread can only read from diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 175c2c1d672..4aed32139e7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -82,6 +82,7 @@ #include <myisam.h> #include <my_dir.h> #include "rpl_handler.h" +#include "rpl_mi.h" #include "sp_head.h" #include "sp.h" @@ -1296,8 +1297,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } else #endif - if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, ¬_used)) - break; + { + thd->lex->relay_log_connection_name.str= (char*) ""; + thd->lex->relay_log_connection_name.length= 0; + if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, ¬_used)) + break; + } if (trans_commit_implicit(thd)) break; close_thread_tables(thd); @@ -2343,10 +2348,42 @@ case SQLCOM_PREPARE: #ifdef HAVE_REPLICATION case SQLCOM_CHANGE_MASTER: { + LEX_MASTER_INFO *lex_mi= &thd->lex->mi; + Master_info *mi; + bool new_master= 0; + if (check_global_access(thd, SUPER_ACL)) goto error; mysql_mutex_lock(&LOCK_active_mi); - res = change_master(thd,active_mi); + + mi= master_info_index->get_master_info(&lex_mi->connection_name, + MYSQL_ERROR::WARN_LEVEL_NOTE); + + if (mi == NULL) + { + /* New replication created */ + mi= new Master_info(&lex_mi->connection_name, relay_log_recovery); + if (!mi || mi->error()) + { + delete mi; + res= 1; + mysql_mutex_unlock(&LOCK_active_mi); + break; + } + new_master= 1; + } + + res= change_master(thd, mi); + if (res && new_master) + { + /* + The new master was added by change_master(). Remove it as it didn't + work. + */ + master_info_index->remove_master_info(&lex_mi->connection_name); + delete mi; + } + mysql_mutex_unlock(&LOCK_active_mi); break; } @@ -2356,15 +2393,19 @@ case SQLCOM_PREPARE: if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) goto error; mysql_mutex_lock(&LOCK_active_mi); - if (active_mi != NULL) - { - res = show_master_info(thd, active_mi); - } + + if (lex->verbose) + res= show_all_master_info(thd); else { - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO)); - my_ok(thd); + LEX_MASTER_INFO *lex_mi= &thd->lex->mi; + Master_info *mi; + mi= master_info_index->get_master_info(&lex_mi->connection_name, + MYSQL_ERROR::WARN_LEVEL_ERROR); + if (mi != NULL) + { + res= show_master_info(thd, mi, 0); + } } mysql_mutex_unlock(&LOCK_active_mi); break; @@ -2664,40 +2705,79 @@ end_with_restore_list: #ifdef HAVE_REPLICATION case SQLCOM_SLAVE_START: { + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + Master_info *mi; mysql_mutex_lock(&LOCK_active_mi); - start_slave(thd,active_mi,1 /* net report*/); + + if ((mi= (master_info_index-> + get_master_info(&lex_mi->connection_name, + MYSQL_ERROR::WARN_LEVEL_ERROR)))) + if (!start_slave(thd, mi, 1 /* net report*/)) + my_ok(thd); mysql_mutex_unlock(&LOCK_active_mi); break; } case SQLCOM_SLAVE_STOP: - /* - If the client thread has locked tables, a deadlock is possible. - Assume that - - the client thread does LOCK TABLE t READ. - - then the master updates t. - - then the SQL slave thread wants to update t, - so it waits for the client thread because t is locked by it. + { + LEX_MASTER_INFO *lex_mi; + Master_info *mi; + /* + If the client thread has locked tables, a deadlock is possible. + Assume that + - the client thread does LOCK TABLE t READ. + - then the master updates t. + - then the SQL slave thread wants to update t, + so it waits for the client thread because t is locked by it. - then the client thread does SLAVE STOP. SLAVE STOP waits for the SQL slave thread to terminate its update t, which waits for the client thread because t is locked by it. - To prevent that, refuse SLAVE STOP if the - client thread has locked tables - */ - if (thd->locked_tables_mode || - thd->in_active_multi_stmt_transaction() || thd->global_read_lock.is_acquired()) + To prevent that, refuse SLAVE STOP if the + client thread has locked tables + */ + if (thd->locked_tables_mode || + thd->in_active_multi_stmt_transaction() || + thd->global_read_lock.is_acquired()) + { + my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, + ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); + goto error; + } + + lex_mi= &thd->lex->mi; + mysql_mutex_lock(&LOCK_active_mi); + if ((mi= (master_info_index-> + get_master_info(&lex_mi->connection_name, + MYSQL_ERROR::WARN_LEVEL_ERROR)))) + if (!stop_slave(thd, mi, 1/* net report*/)) + my_ok(thd); + mysql_mutex_unlock(&LOCK_active_mi); + break; + } + case SQLCOM_SLAVE_ALL_START: { - my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, - ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); - goto error; + mysql_mutex_lock(&LOCK_active_mi); + if (!master_info_index->start_all_slaves(thd)) + my_ok(thd); + mysql_mutex_unlock(&LOCK_active_mi); + break; } + case SQLCOM_SLAVE_ALL_STOP: { + if (thd->locked_tables_mode || + thd->in_active_multi_stmt_transaction() || + thd->global_read_lock.is_acquired()) + { + my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, + ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); + goto error; + } mysql_mutex_lock(&LOCK_active_mi); - stop_slave(thd,active_mi,1/* net report*/); + if (!master_info_index->stop_all_slaves(thd)) + my_ok(thd); mysql_mutex_unlock(&LOCK_active_mi); break; } #endif /* HAVE_REPLICATION */ - case SQLCOM_RENAME_TABLE: { if (execute_rename_table(thd, first_table, all_tables)) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index ed437c498e6..2954e9e1016 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2151,6 +2151,8 @@ static bool check_prepared_statement(Prepared_statement *stmt) case SQLCOM_FLUSH: case SQLCOM_SLAVE_START: case SQLCOM_SLAVE_STOP: + case SQLCOM_SLAVE_ALL_START: + case SQLCOM_SLAVE_ALL_STOP: case SQLCOM_INSTALL_PLUGIN: case SQLCOM_UNINSTALL_PLUGIN: case SQLCOM_CREATE_DB: diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index 914b9026014..99fe9267589 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -26,6 +26,7 @@ #include "sql_repl.h" // reset_master, reset_slave #include "rpl_mi.h" // Master_info::data_lock #include "debug_sync.h" +#include "rpl_mi.h" static void disable_checkpoints(THD *thd); @@ -157,10 +158,36 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, if (options & REFRESH_RELAY_LOG) { #ifdef HAVE_REPLICATION - mysql_mutex_lock(&active_mi->data_lock); - if (rotate_relay_log(active_mi)) - *write_to_binlog= -1; - mysql_mutex_unlock(&active_mi->data_lock); + LEX_STRING connection_name; + Master_info *mi; + if (thd) + connection_name= thd->lex->relay_log_connection_name; + else + { + connection_name.str= (char*) ""; + connection_name.length= 0; + } + + /* + Writing this command to the binlog may cause problems as the + slave is not likely to have the same connection names. + */ + tmp_write_to_binlog= 0; + mysql_mutex_lock(&LOCK_active_mi); + if (!(mi= (master_info_index-> + get_master_info(&connection_name, + MYSQL_ERROR::WARN_LEVEL_ERROR)))) + { + result= 1; + } + else + { + mysql_mutex_lock(&mi->data_lock); + if (rotate_relay_log(mi)) + *write_to_binlog= -1; + mysql_mutex_unlock(&mi->data_lock); + } + mysql_mutex_unlock(&LOCK_active_mi); #endif } #ifdef HAVE_QUERY_CACHE @@ -314,13 +341,27 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, #ifdef HAVE_REPLICATION if (options & REFRESH_SLAVE) { + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + Master_info *mi; tmp_write_to_binlog= 0; mysql_mutex_lock(&LOCK_active_mi); - if (reset_slave(thd, active_mi)) + + if (!(mi= (master_info_index-> + get_master_info(&lex_mi->connection_name, + MYSQL_ERROR::WARN_LEVEL_ERROR)))) + { + result= 1; + } + else if (reset_slave(thd, mi)) { /* NOTE: my_error() has been already called by reset_slave(). */ result= 1; } + else if (mi->connection_name.length && thd->lex->reset_slave_info.all) + { + /* If not default connection and 'all' is used */ + master_info_index->remove_master_info(&mi->connection_name); + } mysql_mutex_unlock(&LOCK_active_mi); } #endif diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 079aab27101..e18b0cd04c0 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -34,14 +34,6 @@ my_bool opt_sporadic_binlog_dump_fail = 0; static int binlog_dump_count = 0; #endif -/** - a copy of active_mi->rli->slave_skip_counter, for showing in SHOW VARIABLES, - INFORMATION_SCHEMA.GLOBAL_VARIABLES and @@sql_slave_skip_counter without - taking all the mutexes needed to access active_mi->rli->slave_skip_counter - properly. -*/ -uint sql_slave_skip_counter; - extern TYPELIB binlog_checksum_typelib; /* @@ -1305,15 +1297,28 @@ err: @retval 0 success @retval 1 error + @retval -1 fatal error */ + int start_slave(THD* thd , Master_info* mi, bool net_report) { int slave_errno= 0; int thread_mask; + char master_info_file_tmp[FN_REFLEN]; + char relay_log_info_file_tmp[FN_REFLEN]; DBUG_ENTER("start_slave"); if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0)) - DBUG_RETURN(1); + DBUG_RETURN(-1); + + create_logfile_name_with_suffix(master_info_file_tmp, + sizeof(master_info_file_tmp), + master_info_file, 0, &mi->connection_name); + create_logfile_name_with_suffix(relay_log_info_file_tmp, + sizeof(relay_log_info_file_tmp), + relay_log_info_file, 0, + &mi->connection_name); + lock_slave_threads(mi); // this allows us to cleanly read slave_running // Get a mask of _stopped_ threads init_thread_mask(&thread_mask,mi,1 /* inverse */); @@ -1327,7 +1332,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) thread_mask&= thd->lex->slave_thd_opt; if (thread_mask) //some threads are stopped, start them { - if (init_master_info(mi,master_info_file,relay_log_info_file, 0, + if (init_master_info(mi,master_info_file_tmp,relay_log_info_file_tmp, 0, thread_mask)) slave_errno=ER_MASTER_INFO; else if (server_id_supplied && *mi->host) @@ -1401,10 +1406,11 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) if (!slave_errno) slave_errno = start_slave_threads(0 /*no mutex */, - 1 /* wait for start */, - mi, - master_info_file,relay_log_info_file, - thread_mask); + 1 /* wait for start */, + mi, + master_info_file_tmp, + relay_log_info_file_tmp, + thread_mask); } else slave_errno = ER_BAD_SLAVE; @@ -1421,11 +1427,11 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) if (slave_errno) { if (net_report) - my_message(slave_errno, ER(slave_errno), MYF(0)); - DBUG_RETURN(1); + my_error(slave_errno, MYF(0), + (int) mi->connection_name.length, + mi->connection_name.str); + DBUG_RETURN(slave_errno == ER_BAD_SLAVE ? -1 : 1); } - else if (net_report) - my_ok(thd); DBUG_RETURN(0); } @@ -1443,17 +1449,17 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) @retval 0 success @retval 1 error + @retval -1 error */ + int stop_slave(THD* thd, Master_info* mi, bool net_report ) { - DBUG_ENTER("stop_slave"); - int slave_errno; - if (!thd) - thd = current_thd; + DBUG_ENTER("stop_slave"); + DBUG_PRINT("enter",("Connection: %s", mi->connection_name.str)); if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0)) - DBUG_RETURN(1); + DBUG_RETURN(-1); thd_proc_info(thd, "Killing slave"); int thread_mask; lock_slave_threads(mi); @@ -1489,8 +1495,6 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) my_message(slave_errno, ER(slave_errno), MYF(0)); DBUG_RETURN(1); } - else if (net_report) - my_ok(thd); DBUG_RETURN(0); } @@ -1514,15 +1518,18 @@ int reset_slave(THD *thd, Master_info* mi) int thread_mask= 0, error= 0; uint sql_errno=ER_UNKNOWN_ERROR; const char* errmsg= "Unknown error occured while reseting slave"; + char master_info_file_tmp[FN_REFLEN]; + char relay_log_info_file_tmp[FN_REFLEN]; DBUG_ENTER("reset_slave"); lock_slave_threads(mi); init_thread_mask(&thread_mask,mi,0 /* not inverse */); if (thread_mask) // We refuse if any slave thread is running { - sql_errno= ER_SLAVE_MUST_STOP; - error=1; - goto err; + unlock_slave_threads(mi); + my_error(ER_SLAVE_MUST_STOP, MYF(0), (int) mi->connection_name.length, + mi->connection_name.str); + DBUG_RETURN(ER_SLAVE_MUST_STOP); } ha_reset_slave(thd); @@ -1549,22 +1556,35 @@ int reset_slave(THD *thd, Master_info* mi) // close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0 end_master_info(mi); + // and delete these two files - fn_format(fname, master_info_file, mysql_data_home, "", 4+32); + create_logfile_name_with_suffix(master_info_file_tmp, + sizeof(master_info_file_tmp), + master_info_file, 0, &mi->connection_name); + create_logfile_name_with_suffix(relay_log_info_file_tmp, + sizeof(relay_log_info_file_tmp), + relay_log_info_file, 0, &mi->connection_name); + + fn_format(fname, master_info_file_tmp, mysql_data_home, "", 4+32); if (mysql_file_stat(key_file_master_info, fname, &stat_area, MYF(0)) && mysql_file_delete(key_file_master_info, fname, MYF(MY_WME))) { error=1; goto err; } + else if (global_system_variables.log_warnings > 1) + sql_print_information("Deleted Master_info file '%s'.", fname); + // delete relay_log_info_file - fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32); + fn_format(fname, relay_log_info_file_tmp, mysql_data_home, "", 4+32); if (mysql_file_stat(key_file_relay_log_info, fname, &stat_area, MYF(0)) && mysql_file_delete(key_file_relay_log_info, fname, MYF(MY_WME))) { error=1; goto err; } + else if (global_system_variables.log_warnings > 1) + sql_print_information("Deleted Master_info file '%s'.", fname); RUN_HOOK(binlog_relay_io, after_reset_slave, (thd, mi)); err: @@ -1644,20 +1664,12 @@ bool change_master(THD* thd, Master_info* mi) char saved_host[HOSTNAME_LENGTH + 1]; uint saved_port; char saved_log_name[FN_REFLEN]; + char master_info_file_tmp[FN_REFLEN]; + char relay_log_info_file_tmp[FN_REFLEN]; my_off_t saved_log_pos; - DBUG_ENTER("change_master"); - - lock_slave_threads(mi); - init_thread_mask(&thread_mask,mi,0 /*not inverse*/); LEX_MASTER_INFO* lex_mi= &thd->lex->mi; - if (thread_mask) // We refuse if any slave thread is running - { - my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0)); - ret= TRUE; - goto err; - } + DBUG_ENTER("change_master"); - thd_proc_info(thd, "Changing master"); /* We need to check if there is an empty master_host. Otherwise change master succeeds, a master.info file is created containing @@ -1665,17 +1677,61 @@ bool change_master(THD* thd, Master_info* mi) is thrown stating that the server is not configured as slave. (See BUG#28796). */ - if(lex_mi->host && !*lex_mi->host) + if (lex_mi->host && !*lex_mi->host) { my_error(ER_WRONG_ARGUMENTS, MYF(0), "MASTER_HOST"); - unlock_slave_threads(mi); DBUG_RETURN(TRUE); } - // TODO: see if needs re-write - if (init_master_info(mi, master_info_file, relay_log_info_file, 0, + if (master_info_index->check_duplicate_master_info(&lex_mi->connection_name, + lex_mi->host, + lex_mi->port)) + DBUG_RETURN(TRUE); + + lock_slave_threads(mi); + init_thread_mask(&thread_mask,mi,0 /*not inverse*/); + if (thread_mask) // We refuse if any slave thread is running + { + my_error(ER_SLAVE_MUST_STOP, MYF(0), (int) mi->connection_name.length, + mi->connection_name.str); + ret= TRUE; + goto err; + } + + thd_proc_info(thd, "Changing master"); + + create_logfile_name_with_suffix(master_info_file_tmp, + sizeof(master_info_file_tmp), + master_info_file, 0, &mi->connection_name); + create_logfile_name_with_suffix(relay_log_info_file_tmp, + sizeof(relay_log_info_file_tmp), + relay_log_info_file, 0, &mi->connection_name); + + /* if new Master_info doesn't exists, add it */ + if (!master_info_index->get_master_info(&mi->connection_name, + MYSQL_ERROR::WARN_LEVEL_NOTE)) + { + if (master_info_index->add_master_info(mi, TRUE)) + { + my_error(ER_MASTER_INFO, MYF(0), + (int) lex_mi->connection_name.length, + lex_mi->connection_name.str); + ret= TRUE; + goto err; + } + } + if (global_system_variables.log_warnings > 1) + sql_print_information("Master: '%.*s' Master_info_file: '%s' " + "Relay_info_file: '%s'", + (int) mi->connection_name.length, + mi->connection_name.str, + master_info_file_tmp, relay_log_info_file_tmp); + + if (init_master_info(mi, master_info_file_tmp, relay_log_info_file_tmp, 0, thread_mask)) { - my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0)); + my_error(ER_MASTER_INFO, MYF(0), + (int) lex_mi->connection_name.length, + lex_mi->connection_name.str); ret= TRUE; goto err; } @@ -1939,7 +1995,7 @@ int reset_master(THD* thd) return 1; } - if (mysql_bin_log.reset_logs(thd)) + if (mysql_bin_log.reset_logs(thd, 1)) return 1; RUN_HOOK(binlog_transmit, after_reset_master, (thd, 0 /* flags */)); return 0; @@ -1965,6 +2021,7 @@ bool mysql_show_binlog_events(THD* thd) File file = -1; MYSQL_BIN_LOG *binary_log= NULL; int old_max_allowed_packet= thd->variables.max_allowed_packet; + Master_info *mi= 0; LOG_INFO linfo; DBUG_ENTER("mysql_show_binlog_events"); @@ -1994,10 +2051,15 @@ bool mysql_show_binlog_events(THD* thd) } else /* showing relay log contents */ { - if (!active_mi) + mysql_mutex_lock(&LOCK_active_mi); + if (!(mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_ERROR))) + { + mysql_mutex_unlock(&LOCK_active_mi); DBUG_RETURN(TRUE); - - binary_log= &(active_mi->rli.relay_log); + } + binary_log= &(mi->rli.relay_log); } if (binary_log->is_open()) @@ -2011,6 +2073,13 @@ bool mysql_show_binlog_events(THD* thd) mysql_mutex_t *log_lock = binary_log->get_log_lock(); Log_event* ev; + if (mi) + { + /* We can unlock the mutex as we have a lock on the file */ + mysql_mutex_unlock(&LOCK_active_mi); + mi= 0; + } + unit->set_limit(thd->lex->current_select); limit_start= unit->offset_limit_cnt; limit_end= unit->select_limit_cnt; @@ -2105,6 +2174,9 @@ bool mysql_show_binlog_events(THD* thd) mysql_mutex_unlock(log_lock); } + else if (mi) + mysql_mutex_unlock(&LOCK_active_mi); + // Check that linfo is still on the function scope. DEBUG_SYNC(thd, "after_show_binlog_events"); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8a106b8ec6f..c87538681a2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2335,6 +2335,7 @@ static bool show_status_array(THD *thd, const char *wild, for (; variables->name; variables++) { + bool wild_checked; strnmov(prefix_end, variables->name, len); name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ if (ucase_names) @@ -2343,11 +2344,25 @@ static bool show_status_array(THD *thd, const char *wild, restore_record(table, s->default_values); table->field[0]->store(name_buffer, strlen(name_buffer), system_charset_info); + + /* + Compare name for types that can't return arrays. We do this to not + calculate the value for function variables that we will not access + */ + if ((variables->type != SHOW_FUNC && variables->type != SHOW_ARRAY)) + { + if (wild && wild[0] && wild_case_compare(system_charset_info, + name_buffer, wild)) + continue; + wild_checked= 1; // Avoid checking it again + } + /* - if var->type is SHOW_FUNC, call the function. - Repeat as necessary, if new var is again SHOW_FUNC + if var->type is SHOW_FUNC or SHOW_SIMPLE_FUNC, call the function. + Repeat as necessary, if new var is again one of the above */ - for (var=variables; var->type == SHOW_FUNC; var= &tmp) + for (var=variables; var->type == SHOW_FUNC || + var->type == SHOW_SIMPLE_FUNC; var= &tmp) ((mysql_show_var_func)(var->value))(thd, &tmp, buff); SHOW_TYPE show_type=var->type; @@ -2358,8 +2373,9 @@ static bool show_status_array(THD *thd, const char *wild, } else { - if (!(wild && wild[0] && wild_case_compare(system_charset_info, - name_buffer, wild)) && + if ((wild_checked || + (wild && wild[0] && wild_case_compare(system_charset_info, + name_buffer, wild))) && (!partial_cond || partial_cond->val_int())) { char *value=var->value; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 555efaf366d..142911efd03 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -65,6 +65,7 @@ #include <myisammrg.h> #include "keycaches.h" #include "set_var.h" +#include "rpl_mi.h" /* this is to get the bison compilation windows warnings out */ #ifdef _MSC_VER @@ -1291,6 +1292,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SIGNED_SYM %token SIMPLE_SYM /* SQL-2003-N */ %token SLAVE +%token SLAVES %token SLOW %token SMALLINT /* SQL-2003-R */ %token SNAPSHOT_SYM @@ -1904,7 +1906,7 @@ help: /* change master */ change: - CHANGE MASTER_SYM TO_SYM + CHANGE MASTER_SYM optional_connection_name TO_SYM { Lex->sql_command = SQLCOM_CHANGE_MASTER; } @@ -2053,6 +2055,29 @@ master_file_def: } ; +optional_connection_name: + /* empty */ + { + THD *thd= YYTHD; + LEX *lex= thd->lex; + lex->mi.connection_name= thd->variables.default_master_connection; + } + | connection_name; + ; + +connection_name: + TEXT_STRING_sys + { + Lex->mi.connection_name= $1; +#ifdef HAVE_REPLICATION + if (check_master_connection_name(&$1)) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME"); + MYSQL_YYABORT; + } +#endif + } + /* create a table */ create: @@ -7074,7 +7099,7 @@ opt_to: */ slave: - START_SYM SLAVE slave_thread_opts + START_SYM SLAVE optional_connection_name slave_thread_opts { LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_START; @@ -7083,14 +7108,28 @@ slave: } slave_until {} - | STOP_SYM SLAVE slave_thread_opts + | START_SYM ALL SLAVES slave_thread_opts + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_ALL_START; + lex->type = 0; + } + {} + | STOP_SYM SLAVE optional_connection_name slave_thread_opts { LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_STOP; lex->type = 0; /* If you change this code don't forget to update SLAVE STOP too */ } - | SLAVE START_SYM slave_thread_opts + | STOP_SYM ALL SLAVES slave_thread_opts + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_ALL_STOP; + lex->type = 0; + /* If you change this code don't forget to update SLAVE STOP too */ + } + | SLAVE optional_connection_name START_SYM slave_thread_opts { LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_START; @@ -7098,7 +7137,7 @@ slave: } slave_until {} - | SLAVE STOP_SYM slave_thread_opts + | SLAVE optional_connection_name STOP_SYM slave_thread_opts { LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_STOP; @@ -11429,7 +11468,7 @@ show_param: LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS; } opt_limit_clause_init - | RELAYLOG_SYM EVENTS_SYM binlog_in binlog_from + | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS; @@ -11558,9 +11597,23 @@ show_param: { Lex->sql_command = SQLCOM_SHOW_MASTER_STAT; } + | ALL SLAVES STATUS_SYM + { + Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; + Lex->verbose= 1; + } | SLAVE STATUS_SYM { + THD *thd= YYTHD; + LEX *lex= thd->lex; + lex->mi.connection_name= thd->variables.default_master_connection; + lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; + lex->verbose= 0; + } + | SLAVE connection_name STATUS_SYM + { Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; + Lex->verbose= 0; } | CLIENT_STATS_SYM { @@ -11812,8 +11865,17 @@ flush_option: { Lex->type|= REFRESH_SLOW_LOG; } | BINARY LOGS_SYM { Lex->type|= REFRESH_BINARY_LOG; } - | RELAY LOGS_SYM - { Lex->type|= REFRESH_RELAY_LOG; } + | RELAY LOGS_SYM optional_connection_name + { + LEX *lex= Lex; + if (lex->type & REFRESH_RELAY_LOG) + { + my_error(ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS"); + MYSQL_YYABORT; + } + lex->type|= REFRESH_RELAY_LOG; + lex->relay_log_connection_name= lex->mi.connection_name; + } | QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE_FREE; } | HOSTS_SYM @@ -11821,13 +11883,23 @@ flush_option: | PRIVILEGES { Lex->type|= REFRESH_GRANT; } | LOGS_SYM - { Lex->type|= REFRESH_LOG; } + { + Lex->type|= REFRESH_LOG; + Lex->relay_log_connection_name.str= (char*) ""; + Lex->relay_log_connection_name.length= 0; + } | STATUS_SYM { Lex->type|= REFRESH_STATUS; } - | SLAVE + | SLAVE optional_connection_name { - Lex->type|= REFRESH_SLAVE; - Lex->reset_slave_info.all= false; + LEX *lex= Lex; + if (lex->type & REFRESH_SLAVE) + { + my_error(ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE"); + MYSQL_YYABORT; + } + lex->type|= REFRESH_SLAVE; + lex->reset_slave_info.all= false; } | CLIENT_STATS_SYM { Lex->type|= REFRESH_CLIENT_STATS; } @@ -11871,6 +11943,7 @@ reset_options: reset_option: SLAVE { Lex->type|= REFRESH_SLAVE; } + optional_connection_name slave_reset_options { } | MASTER_SYM { Lex->type|= REFRESH_MASTER; } | QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE;} @@ -12969,6 +13042,7 @@ keyword: | SIGNED_SYM {} | SOCKET_SYM {} | SLAVE {} + | SLAVES {} | SONAME_SYM {} | START_SYM {} | STOP_SYM {} diff --git a/sql/strfunc.cc b/sql/strfunc.cc index 0c0742b3805..9603ca30cfa 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -15,6 +15,7 @@ /* Some useful string utility functions used by the MySQL server */ +#include <my_global.h> #include "sql_priv.h" #include "unireg.h" #include "strfunc.h" diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 4a003a89a7e..5eb75687dff 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -796,6 +796,30 @@ static Sys_var_lexstring Sys_init_connect( DEFAULT(""), &PLock_sys_init_connect, NOT_IN_BINLOG, ON_CHECK(check_init_string)); +#ifdef HAVE_REPLICATION +static bool check_master_connection(sys_var *self, THD *thd, set_var *var) +{ + LEX_STRING tmp; + tmp.str= var->save_result.string_value.str; + tmp.length= var->save_result.string_value.length; + if (!tmp.str || check_master_connection_name(&tmp)) + { + my_error(ER_WRONG_ARGUMENTS, MYF(ME_JUST_WARNING), + var->var->name.str); + return true; + } + return false; +} + +static Sys_var_session_lexstring Sys_default_master_connection( + "default_master_connection", + "Master connection to use for all slave variables and slave commands", + SESSION_ONLY(default_master_connection), + NO_CMD_LINE, IN_SYSTEM_CHARSET, + DEFAULT(""), MAX_CONNECTION_NAME, ON_CHECK(check_master_connection), + ON_UPDATE(0)); +#endif + static Sys_var_charptr Sys_init_file( "init_file", "Read SQL commands from this file at startup", READ_ONLY GLOBAL_VAR(opt_init_file), @@ -1081,16 +1105,12 @@ static Sys_var_ulonglong Sys_max_binlog_stmt_cache_size( static bool fix_max_binlog_size(sys_var *self, THD *thd, enum_var_type type) { mysql_bin_log.set_max_size(max_binlog_size); -#ifdef HAVE_REPLICATION - if (!max_relay_log_size) - active_mi->rli.relay_log.set_max_size(max_binlog_size); -#endif return false; } static Sys_var_ulong Sys_max_binlog_size( "max_binlog_size", "Binary log will be rotated automatically when the size exceeds this " - "value. Will also apply to relay logs if max_relay_log_size is 0", + "value.", GLOBAL_VAR(max_binlog_size), CMD_LINE(REQUIRED_ARG), VALID_RANGE(IO_SIZE, 1024*1024L*1024L), DEFAULT(1024*1024L*1024L), BLOCK_SIZE(IO_SIZE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), @@ -1235,24 +1255,6 @@ static Sys_var_ulong Sys_max_prepared_stmt_count( VALID_RANGE(0, 1024*1024), DEFAULT(16382), BLOCK_SIZE(1), &PLock_prepared_stmt_count); -static bool fix_max_relay_log_size(sys_var *self, THD *thd, enum_var_type type) -{ -#ifdef HAVE_REPLICATION - active_mi->rli.relay_log.set_max_size(max_relay_log_size ? - max_relay_log_size: max_binlog_size); -#endif - return false; -} -static Sys_var_ulong Sys_max_relay_log_size( - "max_relay_log_size", - "If non-zero: relay log will be rotated automatically when the " - "size exceeds this value; if zero: when the size " - "exceeds max_binlog_size", - GLOBAL_VAR(max_relay_log_size), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(0, 1024L*1024*1024), DEFAULT(0), BLOCK_SIZE(IO_SIZE), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), - ON_UPDATE(fix_max_relay_log_size)); - static Sys_var_ulong Sys_max_sort_length( "max_sort_length", "The number of bytes to use when sorting BLOB or TEXT values (only " @@ -2023,50 +2025,22 @@ static Sys_var_mybool Sys_master_verify_checksum( static const char *replicate_events_marked_for_skip_names[]= { "replicate", "filter_on_slave", "filter_on_master", 0 }; -static bool -replicate_events_marked_for_skip_check(sys_var *self, THD *thd, - set_var *var) -{ - int thread_mask; - DBUG_ENTER("sys_var_replicate_events_marked_for_skip_check"); - /* Slave threads must be stopped to change the variable. */ - mysql_mutex_lock(&LOCK_active_mi); - lock_slave_threads(active_mi); - init_thread_mask(&thread_mask, active_mi, 0 /*not inverse*/); - unlock_slave_threads(active_mi); - mysql_mutex_unlock(&LOCK_active_mi); - - if (thread_mask) // We refuse if any slave thread is running - { - my_error(ER_SLAVE_MUST_STOP, MYF(0)); - DBUG_RETURN(true); - } - DBUG_RETURN(false); -} bool Sys_var_replicate_events_marked_for_skip::global_update(THD *thd, set_var *var) { - bool result; - int thread_mask; + bool result= true; // Assume error DBUG_ENTER("Sys_var_replicate_events_marked_for_skip::global_update"); - /* Slave threads must be stopped to change the variable. */ + mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); - lock_slave_threads(active_mi); - init_thread_mask(&thread_mask, active_mi, 0 /*not inverse*/); - if (thread_mask) // We refuse if any slave thread is running - { - my_error(ER_SLAVE_MUST_STOP, MYF(0)); - result= true; - } - else + if (!master_info_index->give_error_if_slave_running()) result= Sys_var_enum::global_update(thd, var); - - unlock_slave_threads(active_mi); mysql_mutex_unlock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_global_system_variables); DBUG_RETURN(result); } + static Sys_var_replicate_events_marked_for_skip Replicate_events_marked_for_skip ("replicate_events_marked_for_skip", "Whether the slave should replicate events that were created with " @@ -2077,8 +2051,7 @@ static Sys_var_replicate_events_marked_for_skip Replicate_events_marked_for_skip "the slave).", GLOBAL_VAR(opt_replicate_events_marked_for_skip), CMD_LINE(REQUIRED_ARG), replicate_events_marked_for_skip_names, DEFAULT(RPL_SKIP_REPLICATE), - NO_MUTEX_GUARD, NOT_IN_BINLOG, - ON_CHECK(replicate_events_marked_for_skip_check)); + NO_MUTEX_GUARD, NOT_IN_BINLOG); #endif @@ -3253,71 +3226,18 @@ static Sys_var_mybool Sys_relay_log_recovery( "processed", GLOBAL_VAR(relay_log_recovery), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); -bool Sys_var_rpl_filter::do_check(THD *thd, set_var *var) -{ - bool status; - - /* - We must not be holding LOCK_global_system_variables here, otherwise we can - deadlock with THD::init() which is invoked from within the slave threads - with opposite locking order. - */ - mysql_mutex_assert_not_owner(&LOCK_global_system_variables); - mysql_mutex_lock(&LOCK_active_mi); - mysql_mutex_lock(&active_mi->rli.run_lock); - - status= active_mi->rli.slave_running; - - mysql_mutex_unlock(&active_mi->rli.run_lock); - mysql_mutex_unlock(&LOCK_active_mi); - - if (status) - my_error(ER_SLAVE_MUST_STOP, MYF(0)); - else - status= Sys_var_charptr::do_string_check(thd, var, charset(thd)); - - return status; -} - -void Sys_var_rpl_filter::lock(void) +bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var) { - /* - Starting a slave thread causes the new thread to attempt to - acquire LOCK_global_system_variables (in THD::init) while - LOCK_active_mi is being held by the thread that initiated - the process. In order to not violate the lock order, unlock - LOCK_global_system_variables before grabbing LOCK_active_mi. - */ - mysql_mutex_unlock(&LOCK_global_system_variables); + bool result= true; // Assume error + mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); - mysql_mutex_lock(&active_mi->rli.run_lock); -} - -void Sys_var_rpl_filter::unlock(void) -{ - mysql_mutex_unlock(&active_mi->rli.run_lock); + if (!master_info_index->give_error_if_slave_running()) + result= set_filter_value(var->save_result.string_value.str); mysql_mutex_unlock(&LOCK_active_mi); - mysql_mutex_lock(&LOCK_global_system_variables); -} - -bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var) -{ - bool slave_running, status= false; - - lock(); - - if (! (slave_running= active_mi->rli.slave_running)) - status= set_filter_value(var->save_result.string_value.str); - - if (slave_running) - my_error(ER_SLAVE_MUST_STOP, MYF(0)); - - unlock(); - - return slave_running || status; + return result; } bool Sys_var_rpl_filter::set_filter_value(const char *value) @@ -3355,8 +3275,6 @@ uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd, LEX_STRING *base) tmp.length(0); - lock(); - switch (opt_id) { case OPT_REPLICATE_DO_DB: rpl_filter->get_do_db(&tmp); @@ -3378,8 +3296,6 @@ uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd, LEX_STRING *base) break; } - unlock(); - return (uchar *) thd->strmake(tmp.ptr(), tmp.length()); } @@ -3429,72 +3345,105 @@ static Sys_var_charptr Sys_slave_load_tmpdir( READ_ONLY GLOBAL_VAR(slave_load_tmpdir), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(0)); -static bool fix_slave_net_timeout(sys_var *self, THD *thd, enum_var_type type) -{ - DEBUG_SYNC(thd, "fix_slave_net_timeout"); - - mysql_mutex_unlock(&LOCK_global_system_variables); - mysql_mutex_lock(&LOCK_active_mi); - DBUG_PRINT("info", ("slave_net_timeout=%u mi->heartbeat_period=%.3f", - slave_net_timeout, - (active_mi? active_mi->heartbeat_period : 0.0))); - if (active_mi && slave_net_timeout < active_mi->heartbeat_period) - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX, - ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX)); - mysql_mutex_unlock(&LOCK_active_mi); - mysql_mutex_lock(&LOCK_global_system_variables); - return false; -} static Sys_var_uint Sys_slave_net_timeout( "slave_net_timeout", "Number of seconds to wait for more data " - "from a master/slave connection before aborting the read", + "from any master/slave connection before aborting the read", GLOBAL_VAR(slave_net_timeout), CMD_LINE(REQUIRED_ARG), VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(SLAVE_NET_TIMEOUT), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), - ON_UPDATE(fix_slave_net_timeout)); + ON_UPDATE(0)); -static bool check_slave_skip_counter(sys_var *self, THD *thd, set_var *var) + +/* + Access a multi_source variable + Return 0 + warning if it doesn't exist +*/ + +uint Sys_var_multi_source_ulong:: +get_master_info_uint_value(THD *thd, ptrdiff_t offset) { - bool result= false; + Master_info *mi; + uint res= 0; // Default value mysql_mutex_lock(&LOCK_active_mi); - mysql_mutex_lock(&active_mi->rli.run_lock); - if (active_mi->rli.slave_running) + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_WARN); + if (mi) { - my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0)); - result= true; + mysql_mutex_lock(&mi->rli.data_lock); + res= *((uint*) (((uchar*) mi) + master_info_offset)); + mysql_mutex_unlock(&mi->rli.data_lock); } - mysql_mutex_unlock(&active_mi->rli.run_lock); - mysql_mutex_unlock(&LOCK_active_mi); - return result; + mysql_mutex_unlock(&LOCK_active_mi); + return res; } -static bool fix_slave_skip_counter(sys_var *self, THD *thd, enum_var_type type) + + +bool update_multi_source_variable(sys_var *self_var, THD *thd, + enum_var_type type) { - mysql_mutex_unlock(&LOCK_global_system_variables); + Sys_var_multi_source_ulong *self= (Sys_var_multi_source_ulong*) self_var; + bool result= true; + Master_info *mi; + mysql_mutex_lock(&LOCK_active_mi); - mysql_mutex_lock(&active_mi->rli.run_lock); - /* - The following test should normally never be true as we test this - in the check function; To be safe against multiple - SQL_SLAVE_SKIP_COUNTER request, we do the check anyway - */ - if (!active_mi->rli.slave_running) + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_ERROR); + if (mi) { - mysql_mutex_lock(&active_mi->rli.data_lock); - active_mi->rli.slave_skip_counter= sql_slave_skip_counter; - mysql_mutex_unlock(&active_mi->rli.data_lock); + mysql_mutex_lock(&mi->rli.run_lock); + mysql_mutex_lock(&mi->rli.data_lock); + result= self->update_variable(thd, mi); + mysql_mutex_unlock(&mi->rli.data_lock); + mysql_mutex_unlock(&mi->rli.run_lock); } - mysql_mutex_unlock(&active_mi->rli.run_lock); mysql_mutex_unlock(&LOCK_active_mi); - mysql_mutex_lock(&LOCK_global_system_variables); - return 0; + return result; } -static Sys_var_uint Sys_slave_skip_counter( - "sql_slave_skip_counter", "sql_slave_skip_counter", - GLOBAL_VAR(sql_slave_skip_counter), NO_CMD_LINE, - VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_slave_skip_counter), - ON_UPDATE(fix_slave_skip_counter)); + +static bool update_slave_skip_counter(sys_var *self, THD *thd, Master_info *mi) +{ + if (mi->rli.slave_running) + { + my_error(ER_SLAVE_MUST_STOP, MYF(0), mi->connection_name.length, + mi->connection_name.str); + return true; + } + /* The value was stored temporarly in thd */ + mi->rli.slave_skip_counter= thd->variables.slave_skip_counter; + return false; +} + + +static Sys_var_multi_source_ulong +Sys_slave_skip_counter("sql_slave_skip_counter", + "Skip the next N events from the master log", + SESSION_VAR(slave_skip_counter), + NO_CMD_LINE, + offsetof(Master_info, rli.slave_skip_counter), + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1), + ON_UPDATE(update_slave_skip_counter)); + + +static bool update_max_relay_log_size(sys_var *self, THD *thd, Master_info *mi) +{ + mi->rli.max_relay_log_size= thd->variables.max_relay_log_size; + mi->rli.relay_log.set_max_size(mi->rli.max_relay_log_size); + return false; +} + +static Sys_var_multi_source_ulong +Sys_max_relay_log_size( "max_relay_log_size", + "relay log will be rotated automatically when the " + "size exceeds this value. If 0 are startup, it's " + "set to max_binlog_size", + SESSION_VAR(max_relay_log_size), + CMD_LINE(REQUIRED_ARG), + offsetof(Master_info, rli.max_relay_log_size), + VALID_RANGE(0, 1024L*1024*1024), DEFAULT(0), + BLOCK_SIZE(IO_SIZE), + ON_UPDATE(update_max_relay_log_size)); static Sys_var_charptr Sys_slave_skip_errors( "slave_skip_errors", "Tells the slave thread to continue " diff --git a/sql/sys_vars.h b/sql/sys_vars.h index 21bebcd762c..b438295c1b0 100644 --- a/sql/sys_vars.h +++ b/sql/sys_vars.h @@ -566,11 +566,13 @@ public: option.var_type= GET_STR; } + bool do_check(THD *thd, set_var *var) + { + return Sys_var_charptr::do_string_check(thd, var, charset(thd)); + } bool check_update_type(Item_result type) { return type != STRING_RESULT; } - bool do_check(THD *thd, set_var *var); - void session_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); } @@ -588,8 +590,6 @@ public: protected: uchar *global_value_ptr(THD *thd, LEX_STRING *base); bool set_filter_value(const char *value); - void lock(void); - void unlock(void); }; /** @@ -633,6 +633,93 @@ public: } }; + +/* + A LEX_STRING stored only in thd->variables + Only to be used for small buffers +*/ + +class Sys_var_session_lexstring: public sys_var +{ + size_t max_length; +public: + Sys_var_session_lexstring(const char *name_arg, + const char *comment, int flag_args, + ptrdiff_t off, size_t size, CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, size_t max_length_arg, + on_check_function on_check_func=0, + on_update_function on_update_func=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + 0, VARIABLE_NOT_IN_BINLOG, on_check_func, on_update_func, + 0, 0),max_length(max_length_arg) + { + option.var_type= GET_NO_ARG; + SYSVAR_ASSERT(scope() == ONLY_SESSION) + *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING; + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (!(res=var->value->val_str(&str))) + { + var->save_result.string_value.str= 0; /* NULL */ + var->save_result.string_value.length= 0; + } + else + { + if (res->length() > max_length) + { + my_error(ER_WRONG_STRING_LENGTH, MYF(0), + res->ptr(), name.str, (int) max_length); + return true; + } + var->save_result.string_value.str= thd->strmake(res->ptr(), + res->length()); + var->save_result.string_value.length= res->length(); + } + return false; + } + bool session_update(THD *thd, set_var *var) + { + LEX_STRING *tmp= &session_var(thd, LEX_STRING); + tmp->length= var->save_result.string_value.length; + /* Store as \0 terminated string (just to be safe) */ + strmake(tmp->str, var->save_result.string_value.str, tmp->length); + return false; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return false; + } + void session_save_default(THD *thd, set_var *var) + { + char *ptr= (char*)(intptr)option.def_value; + var->save_result.string_value.str= ptr; + var->save_result.string_value.length= strlen(ptr); + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + return (uchar*) &session_var(thd, LEX_STRING); + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return NULL; + } + bool check_update_type(Item_result type) + { return type != STRING_RESULT; } +}; + + #ifndef DBUG_OFF /** @@session.dbug and @@global.dbug variables. @@ -1389,6 +1476,7 @@ public: }; #endif /* defined(ENABLED_DEBUG_SYNC) */ + /** The class for bit variables - a variant of boolean that stores the value in a bit. @@ -1854,14 +1942,86 @@ public: const char *comment, int flag_args, ptrdiff_t off, size_t size, CMD_LINE getopt, const char *values[], uint def_val, PolyLock *lock, - enum binlog_status_enum binlog_status_arg, - on_check_function on_check_func) + enum binlog_status_enum binlog_status_arg) :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, - values, def_val, lock, binlog_status_arg, on_check_func) + values, def_val, lock, binlog_status_arg) {} bool global_update(THD *thd, set_var *var); }; +/* + Class for handing multi-source replication variables + Variable values are store in Master_info, but to make it possible to + access variable without locks we also store it thd->variables. + These can be used as GLOBAL or SESSION, but both points to the same + variable. This is to make things compatible with MySQL 5.5 where variables + like sql_slave_skip_counter are GLOBAL. +*/ + +class Sys_var_multi_source_ulong; +class Master_info; + +typedef bool (*on_multi_source_update_function)(sys_var *self, THD *thd, + Master_info *mi); +bool update_multi_source_variable(sys_var *self, + THD *thd, enum_var_type type); + + +class Sys_var_multi_source_ulong :public Sys_var_ulong +{ + ptrdiff_t master_info_offset; + on_multi_source_update_function update_multi_source_variable_func; +public: + Sys_var_multi_source_ulong(const char *name_arg, + const char *comment, int flag_args, + ptrdiff_t off, size_t size, + CMD_LINE getopt, + ptrdiff_t master_info_offset_arg, + uint min_val, uint max_val, uint def_val, + uint block_size, + on_multi_source_update_function on_update_func) + :Sys_var_ulong(name_arg, comment, flag_args, off, size, + getopt, min_val, max_val, def_val, block_size, + 0, VARIABLE_NOT_IN_BINLOG, 0, update_multi_source_variable), + master_info_offset(master_info_offset_arg), + update_multi_source_variable_func(on_update_func) + { + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, uint)= (uint) (var->save_result.ulonglong_value); + /* Value should be moved to multi_master in on_update_func */ + return false; + } + bool global_update(THD *thd, set_var *var) + { + return session_update(thd, var); + } + void session_save_default(THD *thd, set_var *var) + { + /* Use value given in variable declaration */ + global_save_default(thd, var); + } + uchar *session_value_ptr(THD *thd,LEX_STRING *base) + { + uint *tmp, res; + tmp= (uint*) (((uchar*)&(thd->variables)) + offset); + res= get_master_info_uint_value(thd, master_info_offset); + *tmp= res; + return (uchar*) tmp; + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + return session_value_ptr(thd, base); + } + uint get_master_info_uint_value(THD *thd, ptrdiff_t offset); + bool update_variable(THD *thd, Master_info *mi) + { + return update_multi_source_variable_func(this, thd, mi); + } +}; + + /**************************************************************************** Used templates ****************************************************************************/ diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index 2c65fd657a9..81f6cbe707f 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -1097,7 +1097,8 @@ static struct st_mysql_sys_var* example_system_variables[]= { NULL }; -// this is an example of SHOW_FUNC and of my_snprintf() service +// this is an example of SHOW_SIMPLE_FUNC and of my_snprintf() service +// If this function would return an array, one should use SHOW_FUNC static int show_func_example(MYSQL_THD thd, struct st_mysql_show_var *var, char *buf) { @@ -1111,7 +1112,7 @@ static int show_func_example(MYSQL_THD thd, struct st_mysql_show_var *var, static struct st_mysql_show_var func_status[]= { - {"example_func_example", (char *)show_func_example, SHOW_FUNC}, + {"example_func_example", (char *)show_func_example, SHOW_SIMPLE_FUNC}, {0,0,SHOW_UNDEF} }; diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 27a463bf61f..97e83cd9221 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -3591,12 +3591,12 @@ struct st_mysql_storage_engine sphinx_storage_engine = struct st_mysql_show_var sphinx_status_vars[] = { - {"sphinx_total", (char *)sphinx_showfunc_total, SHOW_FUNC}, - {"sphinx_total_found", (char *)sphinx_showfunc_total_found, SHOW_FUNC}, - {"sphinx_time", (char *)sphinx_showfunc_time, SHOW_FUNC}, - {"sphinx_word_count", (char *)sphinx_showfunc_word_count, SHOW_FUNC}, - {"sphinx_words", (char *)sphinx_showfunc_words, SHOW_FUNC}, - {"sphinx_error", (char *)sphinx_showfunc_error, SHOW_FUNC}, + {"sphinx_total", (char *)sphinx_showfunc_total, SHOW_SIMPLE_FUNC}, + {"sphinx_total_found", (char *)sphinx_showfunc_total_found, SHOW_SIMPLE_FUNC}, + {"sphinx_time", (char *)sphinx_showfunc_time, SHOW_SIMPLE_FUNC}, + {"sphinx_word_count", (char *)sphinx_showfunc_word_count, SHOW_SIMPLE_FUNC}, + {"sphinx_words", (char *)sphinx_showfunc_words, SHOW_SIMPLE_FUNC}, + {"sphinx_error", (char *)sphinx_showfunc_error, SHOW_SIMPLE_FUNC}, {0, 0, (enum_mysql_show_type)0} }; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 97a30a81d12..9acda7ed13e 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -3190,7 +3190,9 @@ innobase_commit_low( #ifdef MYSQL_SERVER THD *thd=current_thd; - if (thd && thd_is_replication_slave_thread(thd)) { + if (innobase_overwrite_relay_log_info && + thd && thd_is_replication_slave_thread(thd) && + thd->connection_name.length) { /* Update the replication position info inside InnoDB. In embedded server, does nothing. */ const char *log_file_name, *group_relay_log_name; diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c index ccd58bcf8f7..c38cd91e807 100644 --- a/strings/my_vsnprintf.c +++ b/strings/my_vsnprintf.c @@ -100,6 +100,7 @@ static const char *get_length_arg(const char *fmt, ARGS_INFO *args_arr, (*length)--; DBUG_ASSERT(*fmt == '$' && *length < MAX_ARGS); args_arr[*length].arg_type= 'd'; + args_arr[*length].have_longlong= 0; return fmt+1; } |