summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2013-08-23 14:02:13 +0200
committerunknown <knielsen@knielsen-hq.org>2013-08-23 14:02:13 +0200
commitf9c2b402f437a2278b04d971054fcacc57eb07aa (patch)
tree5e5beb8bd8ab697ca05f3c39ecb53fb85ee7f147
parent62d358295bbf8df16da75dd109c463de796dabe0 (diff)
downloadmariadb-git-f9c2b402f437a2278b04d971054fcacc57eb07aa.tar.gz
MDEV-26: Global transaction ID.
Implement @@gtid_binlog_state. This is the internal state of the binlog (most recent GTID logged for every domain_id and server_id). This allows to save the state before RESET MASTER and restore it afterwards.
-rw-r--r--mysql-test/include/mtr_check.sql1
-rw-r--r--mysql-test/suite/rpl/r/rpl_gtid_basic.result38
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_basic.test43
-rw-r--r--mysql-test/suite/sys_vars/r/gtid_binlog_state_basic.result11
-rw-r--r--mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result8
-rw-r--r--mysql-test/suite/sys_vars/t/gtid_binlog_state_basic.test17
-rw-r--r--sql/log.cc40
-rw-r--r--sql/log.h5
-rw-r--r--sql/rpl_gtid.cc74
-rw-r--r--sql/rpl_gtid.h3
-rw-r--r--sql/rpl_rli.cc2
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sql_reload.cc2
-rw-r--r--sql/sql_repl.cc4
-rw-r--r--sql/sql_repl.h2
-rw-r--r--sql/sys_vars.cc101
-rw-r--r--sql/sys_vars.h41
17 files changed, 383 insertions, 13 deletions
diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql
index 467a3f973c7..9267374e15d 100644
--- a/mysql-test/include/mtr_check.sql
+++ b/mysql-test/include/mtr_check.sql
@@ -32,6 +32,7 @@ BEGIN
AND variable_name != 'INNODB_IBUF_MAX_SIZE'
AND variable_name != 'INNODB_USE_NATIVE_AIO'
AND variable_name not like 'GTID%POS'
+ AND variable_name != 'GTID_BINLOG_STATE'
ORDER BY variable_name;
-- Dump all databases, there should be none
diff --git a/mysql-test/suite/rpl/r/rpl_gtid_basic.result b/mysql-test/suite/rpl/r/rpl_gtid_basic.result
index 9c77f203b22..8ff49bc6899 100644
--- a/mysql-test/suite/rpl/r/rpl_gtid_basic.result
+++ b/mysql-test/suite/rpl/r/rpl_gtid_basic.result
@@ -162,4 +162,42 @@ BINLOG_GTID_POS('master-bin.000001',18446744073709551616)
NULL
Warnings:
Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+*** Some tests of @@GLOBAL.gtid_binlog_state ***
+include/stop_slave.inc
+SET @old_state= @@GLOBAL.gtid_binlog_state;
+SET GLOBAL gtid_binlog_state = '';
+ERROR HY000: This operation is not allowed if any GTID has been logged to the binary log. Run RESET MASTER first to erase the log
+RESET MASTER;
+SET GLOBAL gtid_binlog_state = '';
+FLUSH LOGS;
+show binary logs;
+Log_name File_size
+master-bin.000001 #
+master-bin.000002 #
+SET GLOBAL gtid_binlog_state = '0-1-10,1-2-20,0-3-30';
+show binary logs;
+Log_name File_size
+master-bin.000001 #
+show binlog events in 'master-bin.000001' from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc # # SERVER_VERSION, BINLOG_VERSION
+master-bin.000001 # Gtid_list # # [1-2-20,0-1-10,0-3-30]
+master-bin.000001 # Binlog_checkpoint # # master-bin.000001
+SELECT @@GLOBAL.gtid_binlog_pos;
+@@GLOBAL.gtid_binlog_pos
+1-2-20,0-3-30
+SELECT @@GLOBAL.gtid_binlog_state;
+@@GLOBAL.gtid_binlog_state
+1-2-20,0-1-10,0-3-30
+SET GLOBAL gtid_binlog_state = @old_state;
+ERROR HY000: This operation is not allowed if any GTID has been logged to the binary log. Run RESET MASTER first to erase the log
+RESET MASTER;
+SET GLOBAL gtid_binlog_state = @old_state;
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (1);
+include/start_slave.inc
+SELECT * FROM t1;
+a
+1
+DROP TABLE t1;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test
index 7db9e5390f3..17d03ddc90c 100644
--- a/mysql-test/suite/rpl/t/rpl_gtid_basic.test
+++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test
@@ -160,4 +160,47 @@ eval SELECT BINLOG_GTID_POS('$valid_binlog_name',0);
eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551615);
eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551616);
+
+--echo *** Some tests of @@GLOBAL.gtid_binlog_state ***
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+SET @old_state= @@GLOBAL.gtid_binlog_state;
+
+--error ER_BINLOG_MUST_BE_EMPTY
+SET GLOBAL gtid_binlog_state = '';
+RESET MASTER;
+SET GLOBAL gtid_binlog_state = '';
+FLUSH LOGS;
+--source include/show_binary_logs.inc
+SET GLOBAL gtid_binlog_state = '0-1-10,1-2-20,0-3-30';
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000001
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+SELECT @@GLOBAL.gtid_binlog_pos;
+SELECT @@GLOBAL.gtid_binlog_state;
+--error ER_BINLOG_MUST_BE_EMPTY
+SET GLOBAL gtid_binlog_state = @old_state;
+RESET MASTER;
+SET GLOBAL gtid_binlog_state = @old_state;
+
+# Check that slave can reconnect again, despite the RESET MASTER, as we
+# restored the state.
+
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+
+SELECT * FROM t1;
+
+--connection server_1
+DROP TABLE t1;
+
+
--source include/rpl_end.inc
diff --git a/mysql-test/suite/sys_vars/r/gtid_binlog_state_basic.result b/mysql-test/suite/sys_vars/r/gtid_binlog_state_basic.result
new file mode 100644
index 00000000000..ae845d08086
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/gtid_binlog_state_basic.result
@@ -0,0 +1,11 @@
+SELECT @@GLOBAL.gtid_slave_pos;
+@@GLOBAL.gtid_slave_pos
+
+SET gtid_binlog_state= '';
+ERROR HY000: Variable 'gtid_binlog_state' is a GLOBAL variable and should be set with SET GLOBAL
+SET SESSION gtid_binlog_state= '';
+ERROR HY000: Variable 'gtid_binlog_state' is a GLOBAL variable and should be set with SET GLOBAL
+SET GLOBAL gtid_binlog_state= DEFAULT;
+ERROR 42000: Variable 'gtid_binlog_state' doesn't have a default value
+SELECT @@session.gtid_binlog_state;
+ERROR HY000: Variable 'gtid_binlog_state' is a GLOBAL variable
diff --git a/mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result b/mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result
index e3ef59b7e30..3d880418f31 100644
--- a/mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result
+++ b/mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result
@@ -21,13 +21,13 @@ SELECT @@gtid_slave_pos;
@@gtid_slave_pos
1-2-3,2-4-6
SET GLOBAL gtid_slave_pos= '-1-2-3';
-ERROR HY000: Could not parse GTID list for GTID_POS
+ERROR HY000: Could not parse GTID list
SET GLOBAL gtid_slave_pos= '1-2 -3';
-ERROR HY000: Could not parse GTID list for GTID_POS
+ERROR HY000: Could not parse GTID list
SET GLOBAL gtid_slave_pos= '1-2-3 ';
-ERROR HY000: Could not parse GTID list for GTID_POS
+ERROR HY000: Could not parse GTID list
SET GLOBAL gtid_slave_pos= '1-2-3,2-4';
-ERROR HY000: Could not parse GTID list for GTID_POS
+ERROR HY000: Could not parse GTID list
SET GLOBAL gtid_slave_pos= '0-1-10,0-2-20';
ERROR HY000: GTID 0-2-20 and 0-1-10 conflict (duplicate domain id 0)
SET GLOBAL gtid_slave_pos= '0-1-10,1-2-20,2-3-30,1-20-200,3-4-1';
diff --git a/mysql-test/suite/sys_vars/t/gtid_binlog_state_basic.test b/mysql-test/suite/sys_vars/t/gtid_binlog_state_basic.test
new file mode 100644
index 00000000000..f171086e2ce
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/gtid_binlog_state_basic.test
@@ -0,0 +1,17 @@
+--source include/not_embedded.inc
+
+# Most things with gtid_binlog_state requires binlog enabled, and so is
+# tested in rpl suite.
+
+SELECT @@GLOBAL.gtid_slave_pos;
+
+--error ER_GLOBAL_VARIABLE
+SET gtid_binlog_state= '';
+--error ER_GLOBAL_VARIABLE
+SET SESSION gtid_binlog_state= '';
+
+--error ER_NO_DEFAULT
+SET GLOBAL gtid_binlog_state= DEFAULT;
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@session.gtid_binlog_state;
diff --git a/sql/log.cc b/sql/log.cc
index ddea3805fee..041a0b555d1 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3703,7 +3703,8 @@ err:
1 error
*/
-bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
+bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log,
+ rpl_gtid *init_state, uint32 init_state_len)
{
LOG_INFO linfo;
bool error=0;
@@ -3722,6 +3723,14 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
if (!is_relay_log)
{
+ if (init_state && !is_empty_state())
+ {
+ my_error(ER_BINLOG_MUST_BE_EMPTY, MYF(0));
+ mysql_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_log);
+ DBUG_RETURN(1);
+ }
+
/*
Mark that a RESET MASTER is in progress.
This ensures that a binlog checkpoint will not try to write binlog
@@ -3839,7 +3848,10 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
if (!is_relay_log)
{
- rpl_global_gtid_binlog_state.reset();
+ if (init_state)
+ rpl_global_gtid_binlog_state.load(init_state, init_state_len);
+ else
+ rpl_global_gtid_binlog_state.reset();
}
/* Start logging with a new file */
@@ -5525,6 +5537,30 @@ MYSQL_BIN_LOG::append_state_pos(String *str)
bool
+MYSQL_BIN_LOG::append_state(String *str)
+{
+ bool err;
+
+ mysql_mutex_lock(&rpl_global_gtid_binlog_state.LOCK_binlog_state);
+ err= rpl_global_gtid_binlog_state.append_state(str);
+ mysql_mutex_unlock(&rpl_global_gtid_binlog_state.LOCK_binlog_state);
+ return err;
+}
+
+
+bool
+MYSQL_BIN_LOG::is_empty_state()
+{
+ bool res;
+
+ mysql_mutex_lock(&rpl_global_gtid_binlog_state.LOCK_binlog_state);
+ res= (rpl_global_gtid_binlog_state.count() == 0);
+ mysql_mutex_unlock(&rpl_global_gtid_binlog_state.LOCK_binlog_state);
+ return res;
+}
+
+
+bool
MYSQL_BIN_LOG::find_in_binlog_state(uint32 domain_id, uint32 server_id,
rpl_gtid *out_gtid)
{
diff --git a/sql/log.h b/sql/log.h
index 018ac64eff7..11b9cd289f7 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -751,7 +751,8 @@ 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 create_new_log);
+ bool reset_logs(THD* thd, bool create_new_log,
+ rpl_gtid *init_state, uint32 init_state_len);
void close(uint exiting);
void clear_inuse_flag_when_closing(File file);
@@ -780,6 +781,8 @@ public:
int write_state_to_file();
int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size);
bool append_state_pos(String *str);
+ bool append_state(String *str);
+ bool is_empty_state();
bool find_in_binlog_state(uint32 domain_id, uint32 server_id,
rpl_gtid *out_gtid);
bool lookup_domain_in_binlog_state(uint32 domain_id, rpl_gtid *out_gtid);
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 96dade4d390..62d2d6026ce 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -719,6 +719,45 @@ gtid_parser_helper(char **ptr, char *end, rpl_gtid *out_gtid)
}
+rpl_gtid *
+gtid_parse_string_to_list(const char *str, size_t str_len, uint32 *out_len)
+{
+ char *p= const_cast<char *>(str);
+ char *end= p + str_len;
+ uint32 len= 0, alloc_len= 5;
+ rpl_gtid *list= NULL;
+
+ for (;;)
+ {
+ rpl_gtid gtid;
+
+ if (len >= (((uint32)1 << 28)-1) || gtid_parser_helper(&p, end, &gtid))
+ {
+ my_free(list);
+ return NULL;
+ }
+ if ((!list || len >= alloc_len) &&
+ !(list=
+ (rpl_gtid *)my_realloc(list,
+ (alloc_len= alloc_len*2) * sizeof(rpl_gtid),
+ MYF(MY_FREE_ON_ERROR|MY_ALLOW_ZERO_PTR))))
+ return NULL;
+ list[len++]= gtid;
+
+ if (p == end)
+ break;
+ if (*p != ',')
+ {
+ my_free(list);
+ return NULL;
+ }
+ ++p;
+ }
+ *out_len= len;
+ return list;
+}
+
+
/*
Update the slave replication state with the GTID position obtained from
master when connecting with old-style (filename,offset) position.
@@ -1234,6 +1273,41 @@ rpl_binlog_state::append_pos(String *str)
}
+bool
+rpl_binlog_state::append_state(String *str)
+{
+ uint32 i, j;
+ bool first= true;
+
+ for (i= 0; i < hash.records; ++i)
+ {
+ element *e= (element *)my_hash_element(&hash, i);
+ if (!e->last_gtid)
+ {
+ DBUG_ASSERT(e->hash.records==0);
+ continue;
+ }
+ for (j= 0; j <= e->hash.records; ++j)
+ {
+ const rpl_gtid *gtid;
+ if (j < e->hash.records)
+ {
+ gtid= (rpl_gtid *)my_hash_element(&e->hash, j);
+ if (gtid == e->last_gtid)
+ continue;
+ }
+ else
+ gtid= e->last_gtid;
+
+ if (rpl_slave_state_tostring_helper(str, gtid, &first))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
slave_connection_state::slave_connection_state()
{
my_hash_init(&hash, &my_charset_bin, 32,
diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h
index 8d2c98d54d3..d6da2295abe 100644
--- a/sql/rpl_gtid.h
+++ b/sql/rpl_gtid.h
@@ -163,6 +163,7 @@ struct rpl_binlog_state
int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size);
int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size);
bool append_pos(String *str);
+ bool append_state(String *str);
rpl_gtid *find(uint32 domain_id, uint32 server_id);
rpl_gtid *find_most_recent(uint32 domain_id);
};
@@ -205,5 +206,7 @@ struct slave_connection_state
extern bool rpl_slave_state_tostring_helper(String *dest, const rpl_gtid *gtid,
bool *first);
extern int gtid_check_rpl_slave_state_table(TABLE *table);
+extern rpl_gtid *gtid_parse_string_to_list(const char *p, size_t len,
+ uint32 *out_len);
#endif /* RPL_GTID_H */
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 7b55688ce3c..dd2a151108d 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -1011,7 +1011,7 @@ 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, !just_reset))
+ if (rli->relay_log.reset_logs(thd, !just_reset, NULL, 0))
{
*errmsg = "Failed during log reset";
error=1;
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index abafade698d..97cff25fa31 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6527,7 +6527,7 @@ ER_SQL_DISCOVER_ERROR
ER_FAILED_GTID_STATE_INIT
eng "Failed initializing replication GTID state"
ER_INCORRECT_GTID_STATE
- eng "Could not parse GTID list for GTID_POS"
+ eng "Could not parse GTID list"
ER_CANNOT_UPDATE_GTID_STATE
eng "Could not update replication slave gtid state"
ER_DUPLICATE_GTID_DOMAIN
@@ -6557,3 +6557,5 @@ ER_STORED_FUNCTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
eng "Cannot modify @@session.gtid_domain_id or @@session.gtid_seq_no inside a stored function or trigger"
ER_GTID_POSITION_NOT_FOUND_IN_BINLOG2
eng "Connecting slave requested to start from GTID %u-%u-%llu, which is not in the master's binlog. Since the master's binlog contains GTIDs with higher sequence numbers, it probably means that the slave has diverged due to executing extra errorneous transactions"
+ER_BINLOG_MUST_BE_EMPTY
+ eng "This operation is not allowed if any GTID has been logged to the binary log. Run RESET MASTER first to erase the log"
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index e9c9dc86e41..8a05732173d 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -322,7 +322,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long options,
{
DBUG_ASSERT(thd);
tmp_write_to_binlog= 0;
- if (reset_master(thd))
+ if (reset_master(thd, NULL, 0))
{
/* NOTE: my_error() has been already called by reset_master(). */
result= 1;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 34b2b90c8b2..3e4939b7fa8 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3474,7 +3474,7 @@ err:
@retval 0 success
@retval 1 error
*/
-int reset_master(THD* thd)
+int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len)
{
if (!mysql_bin_log.is_open())
{
@@ -3483,7 +3483,7 @@ int reset_master(THD* thd)
return 1;
}
- if (mysql_bin_log.reset_logs(thd, 1))
+ if (mysql_bin_log.reset_logs(thd, 1, init_state, init_state_len))
return 1;
RUN_HOOK(binlog_transmit, after_reset_master, (thd, 0 /* flags */));
return 0;
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 917da9b598e..da55e3e863f 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -46,7 +46,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report);
bool change_master(THD* thd, Master_info* mi, bool *master_info_added);
bool mysql_show_binlog_events(THD* thd);
int reset_slave(THD *thd, Master_info* mi);
-int reset_master(THD* thd);
+int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len);
bool purge_master_logs(THD* thd, const char* to_log);
bool purge_master_logs_before_date(THD* thd, time_t purge_time);
bool log_in_use(const char* log_name);
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index b35e8bb383c..3827e3f4b67 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1434,6 +1434,107 @@ static Sys_var_mybool Sys_gtid_strict_mode(
"generate an out-of-order binlog if executed.",
GLOBAL_VAR(opt_gtid_strict_mode),
CMD_LINE(OPT_ARG), DEFAULT(FALSE));
+
+
+struct gtid_binlog_state_data { rpl_gtid *list; uint32 list_len; };
+
+bool
+Sys_var_gtid_binlog_state::do_check(THD *thd, set_var *var)
+{
+ String str, *res;
+ struct gtid_binlog_state_data *data;
+ rpl_gtid *list;
+ uint32 list_len;
+
+ DBUG_ASSERT(var->type == OPT_GLOBAL);
+
+ if (!(res= var->value->val_str(&str)))
+ return true;
+ if (thd->in_active_multi_stmt_transaction())
+ {
+ my_error(ER_CANT_DO_THIS_DURING_AN_TRANSACTION, MYF(0));
+ return true;
+ }
+ if (!mysql_bin_log.is_open())
+ {
+ my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(0));
+ return true;
+ }
+ if (!mysql_bin_log.is_empty_state())
+ {
+ my_error(ER_BINLOG_MUST_BE_EMPTY, MYF(0));
+ return true;
+ }
+ if (res->length() == 0)
+ list= NULL;
+ else if (!(list= gtid_parse_string_to_list(res->ptr(), res->length(),
+ &list_len)))
+ {
+ my_error(ER_INCORRECT_GTID_STATE, MYF(0));
+ return true;
+ }
+ if (!(data= (gtid_binlog_state_data *)my_malloc(sizeof(*data), MYF(0))))
+ {
+ my_free(list);
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ data->list= list;
+ data->list_len= list_len;
+ var->save_result.ptr= data;
+ return false;
+}
+
+
+bool
+Sys_var_gtid_binlog_state::global_update(THD *thd, set_var *var)
+{
+ bool res;
+
+ DBUG_ASSERT(var->type == OPT_GLOBAL);
+
+ if (!var->value)
+ {
+ my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
+ return true;
+ }
+
+ struct gtid_binlog_state_data *data=
+ (struct gtid_binlog_state_data *)var->save_result.ptr;
+ mysql_mutex_unlock(&LOCK_global_system_variables);
+ res= (0 != reset_master(thd, data->list, data->list_len));
+ mysql_mutex_lock(&LOCK_global_system_variables);
+ my_free(data->list);
+ my_free(data);
+ return res;
+}
+
+
+uchar *
+Sys_var_gtid_binlog_state::global_value_ptr(THD *thd, LEX_STRING *base)
+{
+ char buf[512];
+ String str(buf, sizeof(buf), system_charset_info);
+ char *p;
+
+ str.length(0);
+ if ((opt_bin_log && mysql_bin_log.append_state(&str)) ||
+ !(p= thd->strmake(str.ptr(), str.length())))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return NULL;
+ }
+
+ return (uchar *)p;
+}
+
+
+static unsigned char opt_gtid_binlog_state_dummy;
+static Sys_var_gtid_binlog_state Sys_gtid_binlog_state(
+ "gtid_binlog_state",
+ "The internal GTID state of the binlog, used to keep track of all "
+ "GTIDs ever logged to the binlog.",
+ GLOBAL_VAR(opt_gtid_binlog_state_dummy), NO_CMD_LINE);
#endif
diff --git a/sql/sys_vars.h b/sql/sys_vars.h
index 260a8af8384..e1c2201da31 100644
--- a/sql/sys_vars.h
+++ b/sql/sys_vars.h
@@ -2167,3 +2167,44 @@ public:
}
uchar *global_value_ptr(THD *thd, LEX_STRING *base);
};
+
+
+/**
+ Class for @@global.gtid_binlog_state.
+*/
+class Sys_var_gtid_binlog_state: public sys_var
+{
+public:
+ Sys_var_gtid_binlog_state(const char *name_arg,
+ const char *comment, int flag_args, ptrdiff_t off, size_t size,
+ CMD_LINE getopt)
+ : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
+ getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
+ NULL, NULL, NULL)
+ {
+ option.var_type= GET_STR;
+ }
+ bool do_check(THD *thd, set_var *var);
+ bool session_update(THD *thd, set_var *var)
+ {
+ DBUG_ASSERT(false);
+ return true;
+ }
+ bool global_update(THD *thd, set_var *var);
+ bool check_update_type(Item_result type) { return type != STRING_RESULT; }
+ void session_save_default(THD *thd, set_var *var)
+ {
+ DBUG_ASSERT(false);
+ }
+ void global_save_default(THD *thd, set_var *var)
+ {
+ /* Record the attempt to use default so we can error. */
+ var->value= 0;
+ }
+ uchar *session_value_ptr(THD *thd, LEX_STRING *base)
+ {
+ DBUG_ASSERT(false);
+ return NULL;
+ }
+ uchar *global_value_ptr(THD *thd, LEX_STRING *base);
+};