diff --git a/mysql-test/main/master_retry_count_basic.opt b/mysql-test/main/master_retry_count_basic.opt new file mode 100644 index 00000000000..1e471f65645 --- /dev/null +++ b/mysql-test/main/master_retry_count_basic.opt @@ -0,0 +1 @@ +--master-retry-count=1 diff --git a/mysql-test/main/master_retry_count_basic.result b/mysql-test/main/master_retry_count_basic.result new file mode 100644 index 00000000000..48fcb727069 --- /dev/null +++ b/mysql-test/main/master_retry_count_basic.result @@ -0,0 +1,76 @@ +# Use `--master-retry-count` when not specified +CHANGE MASTER 'named' TO master_host='example.com'; +CHANGE MASTER TO master_host='127.0.0.1', master_ssl_verify_server_cert=0; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT +FROM performance_schema.replication_connection_configuration; +CHANNEL_NAME CONNECTION_RETRY_COUNT +named 1 + 1 +# Replace when specified +CHANGE MASTER 'named' TO master_retry_count=11; +CHANGE MASTER TO master_retry_count=10; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT +FROM performance_schema.replication_connection_configuration; +CHANNEL_NAME CONNECTION_RETRY_COUNT +named 11 + 10 +# Restore specified config on restart +# restart: --skip-slave-start +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT +FROM performance_schema.replication_connection_configuration; +CHANNEL_NAME CONNECTION_RETRY_COUNT +named 11 + 10 +# Keep specified config on RESET REPLICA +RESET REPLICA 'named'; +RESET REPLICA; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT +FROM performance_schema.replication_connection_configuration; +CHANNEL_NAME CONNECTION_RETRY_COUNT +named 11 + 10 +# Don't replace when not specified +CHANGE MASTER TO master_user='root'; +CHANGE MASTER 'named' TO master_user='root'; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT +FROM performance_schema.replication_connection_configuration; +CHANNEL_NAME CONNECTION_RETRY_COUNT +named 11 + 10 +# 0 internally means "not specified" +CHANGE MASTER TO master_retry_count=0; +CHANGE MASTER 'named' TO master_retry_count=0; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT +FROM performance_schema.replication_connection_configuration; +CHANNEL_NAME CONNECTION_RETRY_COUNT +named 11 + 10 +# Truncates decimals +CHANGE MASTER TO master_retry_count=0.5; +CHANGE MASTER 'named' TO master_retry_count=0.5; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT +FROM performance_schema.replication_connection_configuration; +CHANNEL_NAME CONNECTION_RETRY_COUNT +named 11 + 10 +# Caps values (such as UINT64_MAX + 1) to `--master-retry-count`'s max +CHANGE MASTER TO master_retry_count=18446744073709551616; +CHANGE MASTER 'named' TO master_retry_count=18446744073709551616; +SELECT CHANNEL_NAME +FROM performance_schema.replication_connection_configuration +WHERE CONNECTION_RETRY_COUNT IN (4294967295, 18446744073709551615); +CHANNEL_NAME +named + +# Negative +CHANGE MASTER TO master_retry_count=-1; +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 '-1' at line 1 +CHANGE MASTER 'named' TO master_retry_count=-1; +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 '-1' at line 1 +# NaN +CHANGE MASTER TO master_retry_count='5'; +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 ''5'' at line 1 +CHANGE MASTER 'named' TO master_retry_count='5'; +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 ''5'' at line 1 +# Cleanup +RESET REPLICA 'named' ALL; diff --git a/mysql-test/main/master_retry_count_basic.test b/mysql-test/main/master_retry_count_basic.test new file mode 100644 index 00000000000..0f7d1c11348 --- /dev/null +++ b/mysql-test/main/master_retry_count_basic.test @@ -0,0 +1,68 @@ +# MDEV-25674: Test the `Master_Retry_Count` field of +# CHANGE MASTER [name] TO (no feature testing) +# Two connections tests that the field is now per-connection. +--source include/have_perfschema.inc + +--echo # Use `--master-retry-count` when not specified +CHANGE MASTER 'named' TO master_host='example.com'; +CHANGE MASTER TO master_host='127.0.0.1', master_ssl_verify_server_cert=0; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT + FROM performance_schema.replication_connection_configuration; + +--echo # Replace when specified +CHANGE MASTER 'named' TO master_retry_count=11; +# Default master does not replace named master +CHANGE MASTER TO master_retry_count=10; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT + FROM performance_schema.replication_connection_configuration; + +--echo # Restore specified config on restart +--let $restart_parameters= --skip-slave-start +--source include/restart_mysqld.inc # not_embedded +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT + FROM performance_schema.replication_connection_configuration; + +--echo # Keep specified config on RESET REPLICA +RESET REPLICA 'named'; +RESET REPLICA; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT + FROM performance_schema.replication_connection_configuration; + +--echo # Don't replace when not specified +CHANGE MASTER TO master_user='root'; +CHANGE MASTER 'named' TO master_user='root'; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT + FROM performance_schema.replication_connection_configuration; + +--echo # 0 internally means "not specified" +CHANGE MASTER TO master_retry_count=0; +CHANGE MASTER 'named' TO master_retry_count=0; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT + FROM performance_schema.replication_connection_configuration; + +--echo # Truncates decimals +CHANGE MASTER TO master_retry_count=0.5; +CHANGE MASTER 'named' TO master_retry_count=0.5; +SELECT CHANNEL_NAME, CONNECTION_RETRY_COUNT + FROM performance_schema.replication_connection_configuration; + +--echo # Caps values (such as UINT64_MAX + 1) to `--master-retry-count`'s max +CHANGE MASTER TO master_retry_count=18446744073709551616; +CHANGE MASTER 'named' TO master_retry_count=18446744073709551616; +SELECT CHANNEL_NAME + FROM performance_schema.replication_connection_configuration + WHERE CONNECTION_RETRY_COUNT IN (4294967295, 18446744073709551615); + +--echo # Negative +--error ER_PARSE_ERROR +CHANGE MASTER TO master_retry_count=-1; +--error ER_PARSE_ERROR +CHANGE MASTER 'named' TO master_retry_count=-1; +--echo # NaN +--error ER_PARSE_ERROR +CHANGE MASTER TO master_retry_count='5'; +--error ER_PARSE_ERROR +CHANGE MASTER 'named' TO master_retry_count='5'; + +--echo # Cleanup +RESET REPLICA 'named' ALL; diff --git a/sql/lex.h b/sql/lex.h index d420430545f..72f19da12dd 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -371,6 +371,7 @@ SYMBOL symbols[] = { { "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM)}, { "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM)}, { "MASTER_PORT", SYM(MASTER_PORT_SYM)}, + { "MASTER_RETRY_COUNT", SYM(MASTER_RETRY_COUNT_SYM)}, { "MASTER_SERVER_ID", SYM(MASTER_SERVER_ID_SYM)}, { "MASTER_SSL", SYM(MASTER_SSL_SYM)}, { "MASTER_SSL_CA", SYM(MASTER_SSL_CA_SYM)}, diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 6dc0f62f0f7..ee32f761226 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -35,7 +35,8 @@ Master_info::Master_info(LEX_CSTRING *connection_name_arg, ssl(1), ssl_verify_server_cert(1), fd(-1), io_thd(0), rli(is_slave_recovery), port(MYSQL_PORT), checksum_alg_before_fd(BINLOG_CHECKSUM_ALG_UNDEF), - connect_retry(DEFAULT_CONNECT_RETRY), inited(0), abort_slave(0), + connect_retry(DEFAULT_CONNECT_RETRY), retry_count(master_retry_count), + inited(0), abort_slave(0), slave_running(MYSQL_SLAVE_NOT_RUN), slave_run_id(0), clock_diff_with_master(0), sync_counter(0), heartbeat_period(0), received_heartbeats(0), @@ -569,9 +570,12 @@ file '%s')", fname); goto errwithmsg; /* Starting from 5.5 the master_retry_count may be in the repository. */ - if (lines >= LINE_FOR_MASTER_RETRY_COUNT && - init_strvar_from_file(buf, sizeof(buf), &mi->file, "")) - goto errwithmsg; + if (lines >= LINE_FOR_MASTER_RETRY_COUNT) + { + if (init_strvar_from_file(buf, sizeof(buf), &mi->file, "")) + goto errwithmsg; + mi->retry_count = atol(buf); + } if (lines >= LINE_FOR_SSL_CRLPATH && (init_strvar_from_file(mi->ssl_crl, sizeof(mi->ssl_crl), @@ -831,7 +835,7 @@ int flush_master_info(Master_info* mi, (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert, mi->ssl_cipher, mi->ssl_key, mi->ssl_verify_server_cert, heartbeat_buf, "", ignore_server_ids_buf, - "", 0, + "", mi->retry_count, mi->ssl_crl, mi->ssl_crlpath, mi->using_gtid, do_domain_ids_buf, ignore_domain_ids_buf); err= flush_io_cache(file); diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index 37a5fc30099..fee37f93a61 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -253,7 +253,10 @@ class Master_info : public Slave_reporting_capability @@global.binlog_checksum and deactivated once FD has been received. */ enum_binlog_checksum_alg checksum_alg_before_fd; + /** pause duration between each connection retry */ uint connect_retry; + /** per-slave @ref master_retry_count */ + ulong retry_count; #ifndef DBUG_OFF int events_till_disconnect; diff --git a/sql/slave.cc b/sql/slave.cc index ea21e607bcd..5e02bb9209d 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4390,7 +4390,7 @@ static bool check_io_slave_killed(Master_info *mi, const char *info) @details Terminates current connection to master and initiates new connection with safe_reconnect(), which sleeps for @c mi->connect_retry msecs and increases @c mi->TODO for each attempt - - if it exceeds @c master_retry_count then connection is not re-established + if it exceeds @c mi->retry_count then connection is not re-established and function signals error. Unless @c suppres_warnings is TRUE, a warning is put in the server error log when reconnecting. The warning message and messages used to report errors @@ -6933,7 +6933,7 @@ static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi) IMPLEMENTATION Try to connect until successful or slave killed or we have retried - master_retry_count times + mi->retry_count times */ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, @@ -7016,16 +7016,10 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, " - retry-time: %d maximum-retries: %lu message: %s", (reconnect ? "reconnecting" : "connecting"), mi->user, mi->host, mi->port, - mi->connect_retry, master_retry_count, + mi->connect_retry, mi->retry_count, mysql_error(mysql)); } - /* - By default we try forever. The reason is that failure will trigger - master election, so if the user did not set master_retry_count we - do not want to have election triggered on the first failure to - connect - */ - if (++err_count == master_retry_count) + if (++err_count == mi->retry_count) { slave_was_killed=1; if (reconnect) @@ -7067,7 +7061,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, IMPLEMENTATION Try to connect until successful or slave killed or we have retried - master_retry_count times + mi->retry_count times */ static int safe_reconnect(THD* thd, MYSQL* mysql, Master_info* mi, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7edc5ae0578..2e0a0a21e07 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -351,6 +351,7 @@ struct LEX_MASTER_INFO ulong relay_log_pos; ulong server_id; uint port, connect_retry; + ulong retry_count; float heartbeat_period; int sql_delay; bool is_demotion_opt; @@ -391,7 +392,7 @@ struct LEX_MASTER_INFO host= user= password= log_file_name= ssl_key= ssl_cert= ssl_ca= ssl_capath= ssl_cipher= ssl_crl= ssl_crlpath= relay_log_name= NULL; - pos= relay_log_pos= server_id= port= connect_retry= 0; + pos= relay_log_pos= server_id= port= connect_retry= retry_count= 0; heartbeat_period= 0; ssl= ssl_verify_server_cert= heartbeat_opt= repl_ignore_server_ids_opt= repl_do_domain_ids_opt= diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 2feb276bd7c..f46da50ce7c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -4050,6 +4050,8 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) mi->port = lex_mi->port; if (lex_mi->connect_retry) mi->connect_retry = lex_mi->connect_retry; + if (lex_mi->retry_count) + mi->retry_count= lex_mi->retry_count; if (lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED) mi->heartbeat_period = lex_mi->heartbeat_period; else diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 59f3a714f6a..e874832f169 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -939,6 +939,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token MASTER_LOG_POS_SYM %token MASTER_PASSWORD_SYM %token MASTER_PORT_SYM +%token MASTER_RETRY_COUNT_SYM %token MASTER_SERVER_ID_SYM %token MASTER_SSL_CAPATH_SYM %token MASTER_SSL_CA_SYM @@ -2275,6 +2276,10 @@ master_def: { Lex->mi.connect_retry = $3; } + | MASTER_RETRY_COUNT_SYM '=' ulong_num + { + Lex->mi.retry_count = $3; + } | MASTER_DELAY_SYM '=' ulong_num { if ($3 > MASTER_DELAY_MAX) @@ -16536,6 +16541,7 @@ keyword_func_sp_var_and_label: | MASTER_SERVER_ID_SYM | MASTER_CONNECT_RETRY_SYM | MASTER_DELAY_SYM + | MASTER_RETRY_COUNT_SYM | MASTER_SSL_SYM | MASTER_SSL_CA_SYM | MASTER_SSL_CAPATH_SYM diff --git a/storage/perfschema/table_replication_connection_configuration.cc b/storage/perfschema/table_replication_connection_configuration.cc index 81135074754..71c39b2e98d 100644 --- a/storage/perfschema/table_replication_connection_configuration.cc +++ b/storage/perfschema/table_replication_connection_configuration.cc @@ -255,7 +255,7 @@ void table_replication_connection_configuration::make_row(Master_info *mi) m_row.connection_retry_interval= (unsigned int) mi->connect_retry; - m_row.connection_retry_count= master_retry_count; //(ulong) mi->retry_count; + m_row.connection_retry_count= mi->retry_count; m_row.heartbeat_interval= (double)mi->heartbeat_period;