Skip to content

Commit c39ebbc

Browse files
AliSQLAliSQL
authored andcommitted
[Feature] Issue#39 Modify gtid_executed_set dynamically
Summary: -------- User with super privileges can add other gtid_set(we call it ADD_SET) to gtid_executed_set. This command will also write and rotate binlog. If something is wrong when write binlog or rotate file, the change of gtid_executed_set will rollback, that ADD_SET will be removed from gtid_executed_set. Usage: ------ SET EXECUTED_GTID_SET "00000000-0000-0000-0000-000000000000:1"
1 parent 5cf155e commit c39ebbc

16 files changed

Lines changed: 309 additions & 2 deletions

mysql-test/r/mysqld--help-notwin.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,7 @@ performance-schema-max-rwlock-instances -1
13841384
performance-schema-max-socket-classes 10
13851385
performance-schema-max-socket-instances -1
13861386
performance-schema-max-stage-classes 150
1387-
performance-schema-max-statement-classes 169
1387+
performance-schema-max-statement-classes 170
13881388
performance-schema-max-table-handles -1
13891389
performance-schema-max-table-instances -1
13901390
performance-schema-max-thread-classes 50
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
include/master-slave.inc
2+
Warnings:
3+
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4+
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
5+
[connection master]
6+
grant usage on *.* to tmp@localhost;
7+
show global variables like 'gtid_executed';
8+
Variable_name Value
9+
gtid_executed UUID:1
10+
create table t1(id int) engine = InnoDB;
11+
insert into t1 values(1),(2),(3);
12+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:1-2';
13+
show global variables like 'gtid_executed';
14+
Variable_name Value
15+
gtid_executed 00000000-0000-0000-0000-000000000000:1-2,
16+
UUID:1-4
17+
set session debug='+d,add_executed_gtid_set_rotate_error';
18+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:3-4';
19+
ERROR HY000: set executed_gtid_set fail, error: 'write binlog or binlog rotate failed'.
20+
set session debug='-d,add_executed_gtid_set_rotate_error';
21+
show global variables like 'gtid_executed';
22+
Variable_name Value
23+
gtid_executed 00000000-0000-0000-0000-000000000000:1-4,
24+
UUID:1-5
25+
stop slave;
26+
include/wait_for_slave_to_stop.inc
27+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:1-20';
28+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:9-70';
29+
set executed_gtid_set '00000000-0000-0000-0000-000000000001:9-70';
30+
set executed_gtid_set 'eb0597f-34f7-11e5-be40-00163e000ea5:9-70';
31+
ERROR HY000: Malformed GTID set specification 'eb0597f-34f7-11e5-be40-00163e000ea5:9-70'.
32+
set executed_gtid_set '00000000-0000-0000-0000-000000000001:8-6';
33+
set executed_gtid_set '00000000-0000-0000-0000-000000000001:8--16';
34+
ERROR HY000: Malformed GTID set specification '00000000-0000-0000-0000-000000000001:8--16'.
35+
show global variables like 'gtid_executed';
36+
Variable_name Value
37+
gtid_executed 00000000-0000-0000-0000-000000000000:1-70,
38+
00000000-0000-0000-0000-000000000001:9-70,
39+
UUID:1-9
40+
start slave;
41+
include/wait_for_slave_to_start.inc
42+
show global variables like 'gtid_executed';
43+
Variable_name Value
44+
gtid_executed 00000000-0000-0000-0000-000000000000:1-70,
45+
00000000-0000-0000-0000-000000000001:9-70,
46+
UUID:1-9
47+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:1-2000';
48+
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
49+
show global variables like 'gtid_executed';
50+
Variable_name Value
51+
gtid_executed 00000000-0000-0000-0000-000000000000:1-70,
52+
00000000-0000-0000-0000-000000000001:9-70,
53+
UUID:1-9
54+
drop user tmp@localhost;
55+
drop table t1;
56+
include/rpl_end.inc
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
--gtid-mode=on
2+
--enforce-gtid-consistency
3+
--log-bin
4+
--log-slave-updates
5+
--binlog-format=row
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
--gtid-mode=on
2+
--enforce-gtid-consistency
3+
--log-bin
4+
--log-slave-updates
5+
--binlog-format=row
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
source include/have_debug.inc;
2+
source include/have_binlog_format_row.inc;
3+
source include/master-slave.inc;
4+
--disable_warnings
5+
6+
let $UUID = `select @@server_uuid`;
7+
8+
grant usage on *.* to tmp@localhost;
9+
connect (conn,127.0.0.1,tmp,,test,$MASTER_MYPORT);
10+
11+
connection master;
12+
13+
--replace_result $UUID UUID
14+
show global variables like 'gtid_executed';
15+
16+
create table t1(id int) engine = InnoDB;
17+
insert into t1 values(1),(2),(3);
18+
19+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:1-2';
20+
21+
--replace_result $UUID UUID
22+
show global variables like 'gtid_executed';
23+
24+
set session debug='+d,add_executed_gtid_set_rotate_error';
25+
26+
--error ER_SET_EXECUTED_GTID_SET_FAIL
27+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:3-4';
28+
29+
set session debug='-d,add_executed_gtid_set_rotate_error';
30+
31+
sync_slave_with_master;
32+
connection slave;
33+
34+
--replace_result $UUID UUID
35+
show global variables like 'gtid_executed';
36+
37+
stop slave;
38+
source include/wait_for_slave_to_stop.inc;
39+
40+
connection master;
41+
42+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:1-20';
43+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:9-70';
44+
set executed_gtid_set '00000000-0000-0000-0000-000000000001:9-70';
45+
46+
--error 1772
47+
set executed_gtid_set 'eb0597f-34f7-11e5-be40-00163e000ea5:9-70';
48+
set executed_gtid_set '00000000-0000-0000-0000-000000000001:8-6';
49+
--error 1772
50+
set executed_gtid_set '00000000-0000-0000-0000-000000000001:8--16';
51+
52+
--replace_result $UUID UUID
53+
show global variables like 'gtid_executed';
54+
55+
connection slave;
56+
start slave;
57+
source include/wait_for_slave_to_start.inc;
58+
59+
connection master;
60+
sync_slave_with_master;
61+
62+
connection slave;
63+
--replace_result $UUID UUID
64+
show global variables like 'gtid_executed';
65+
66+
connection conn;
67+
--error 1227
68+
set executed_gtid_set '00000000-0000-0000-0000-000000000000:1-2000';
69+
70+
connection master;
71+
--replace_result $UUID UUID
72+
show global variables like 'gtid_executed';
73+
drop user tmp@localhost;
74+
drop table t1;
75+
sync_slave_with_master;
76+
77+
source include/rpl_end.inc;

sql/lex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ static SYMBOL symbols[] = {
210210
{ "EVERY", SYM(EVERY_SYM)},
211211
{ "EXCHANGE", SYM(EXCHANGE_SYM)},
212212
{ "EXECUTE", SYM(EXECUTE_SYM)},
213+
{ "EXECUTED_GTID_SET",SYM(EXECUTED_GTID_SET)},
213214
{ "EXISTS", SYM(EXISTS)},
214215
{ "EXIT", SYM(EXIT_SYM)},
215216
{ "EXPANSION", SYM(EXPANSION_SYM)},

sql/mysqld.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3512,6 +3512,7 @@ SHOW_VAR com_status_vars[]= {
35123512
{"drop_view", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_VIEW]), SHOW_LONG_STATUS},
35133513
{"empty_query", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS},
35143514
{"execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
3515+
{"executed_gtid_set", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_EXECUTED_GTID_SET]), SHOW_LONG_STATUS},
35153516
{"flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
35163517
{"get_diagnostics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GET_DIAGNOSTICS]), SHOW_LONG_STATUS},
35173518
{"grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},

sql/rpl_gtid.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,16 @@ class Gtid_set
992992
@return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
993993
*/
994994
enum_return_status add_gtid_text(const char *text, bool *anonymous= NULL);
995+
/*
996+
Remove the set of GTIDs represented by the given string to this Gtid_set.
997+
Before calling this function, global_sid_lock->wrlock() should be held.
998+
999+
The string must have the format defined above.
1000+
1001+
@param text The string to parse.
1002+
*/
1003+
enum_return_status remove_gtid_text(const char *text);
1004+
9951005
/**
9961006
Decodes a Gtid_set from the given string.
9971007
@@ -2286,6 +2296,23 @@ class Gtid_state
22862296
@return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
22872297
*/
22882298
enum_return_status add_lost_gtids(const char *text);
2299+
/*
2300+
Not check if the logged_gtids is empty.
2301+
For set_executed_gtid_set.
2302+
2303+
@param text The string to parse.
2304+
@return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2305+
*/
2306+
enum_return_status add_executed_gtids(const char *text);
2307+
2308+
/*
2309+
Remove the given Gtid_set that contains the groups in the given
2310+
string to logged_gtids.
2311+
2312+
@param text The string to parse.
2313+
@return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2314+
*/
2315+
enum_return_status remove_executed_gtids(const char *text);
22892316
/// Return a pointer to the Gtid_set that contains the logged groups.
22902317
const Gtid_set *get_logged_gtids() const { return &logged_gtids; }
22912318
/// Return a pointer to the Gtid_set that contains the logged groups.

sql/rpl_gtid_set.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,29 @@ enum_return_status Gtid_set::add_gtid_text(const char *text, bool *anonymous)
554554
RETURN_REPORTED_ERROR;
555555
}
556556

557+
enum_return_status Gtid_set::remove_gtid_text(const char *text)
558+
{
559+
DBUG_ENTER("Gtid_set::remove_gtid_text");
560+
561+
/*
562+
Init a empty Gtid_set, and add_gtid_text() to the new Gtid_set.
563+
Remove the new Gtid set from this Gtid set.
564+
*/
565+
Gtid_set *tmp_gtid_set= new Gtid_set(sid_map);
566+
567+
enum_return_status ret= tmp_gtid_set->add_gtid_text(text);
568+
569+
if (RETURN_STATUS_OK != ret)
570+
goto end;
571+
572+
ret= this->remove_gtid_set(tmp_gtid_set);
573+
574+
end:
575+
delete tmp_gtid_set;
576+
577+
RETURN_STATUS(ret);
578+
}
579+
557580
bool Gtid_set::is_valid(const char *text)
558581
{
559582
DBUG_ENTER("Gtid_set::is_valid(const char*)");

sql/rpl_gtid_state.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,29 @@ enum_return_status Gtid_state::add_lost_gtids(const char *text)
425425
DBUG_RETURN(RETURN_STATUS_OK);
426426
}
427427

428+
enum_return_status Gtid_state::add_executed_gtids(const char *text)
429+
{
430+
DBUG_ENTER("Gtid_state::add_executed_gtids()");
431+
sid_lock->assert_some_wrlock();
432+
433+
DBUG_PRINT("info", ("add_executed_gtids '%s'", text));
434+
435+
PROPAGATE_REPORTED_ERROR(logged_gtids.add_gtid_text(text));
436+
437+
DBUG_RETURN(RETURN_STATUS_OK);
438+
}
439+
440+
enum_return_status Gtid_state::remove_executed_gtids(const char *text)
441+
{
442+
DBUG_ENTER("Gtid_state::remove_executed_gtids()");
443+
sid_lock->assert_some_wrlock();
444+
445+
DBUG_PRINT("info", ("remove_executed_gtids '%s'", text));
446+
447+
PROPAGATE_REPORTED_ERROR(logged_gtids.remove_gtid_text(text));
448+
449+
DBUG_RETURN(RETURN_STATUS_OK);
450+
}
428451

429452
int Gtid_state::init()
430453
{

0 commit comments

Comments
 (0)