Skip to content

Commit d180878

Browse files
author
Bharathy Satish
committed
Bug #26495619: PERSISTED PLUGIN VARIABLES ARE NOT CONSIDERED DURING
SERVER RESTART Problem: System variables can be set either from command line or through sql using SET statement. Variables set as part of command line does not go through runtime validation, whereas variables set using SET statement are validated using check() function. Thus read only variables are set as part of command line and dynamic variables are set using SET statement. Variables persisted using SET PERSIST or PERSIST_ONLY syntax will ensure that variables are validated using check() when server is restarted, except with an exception for read only variables because they are appended to command line during server startup. There are certain group replication(GR) specific variables which are defined to be DYNAMIC variables, but cannot be changed once GR is up and ONLINE. This kind of behaviour confuses the existing SET statement execution logic. Thus when GR variables are persisted, and later when server is started persisted GR variables could not be set early before GR plugin is loaded. This will not make GR to come ONLINE on boot process. ex: SET PERSIST group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", group_replication_group_seeds="localhost:13011,localhost:13123", group_replication_local_address="localhost:13123", group_replication_bootstrap_group= ON, group_replication_start_on_boot=ON; With above variables persisted, GR should start on boot when server is restarted. This does not happen because SET statement logic expects these variables to be readonly so that these can be set early before plugin is loaded. To obtain this semantics variables needs to be decleared as READ ONLY, and for certain reasons these variables cannot be changed to readonly. Fix: A new flag named PLUGIN_VAR_PERSIST_AS_READ_ONLY is introduced which needs to be set in variable declaration to indicate that these are variables which can be changed before plugin is loaded but not after that. This flag will be checked in SET statement logic and will treat them as a read only variables. Thus when server is restarted these variables can be appended to command line, making GR to start on boot.
1 parent 4b70b54 commit d180878

File tree

7 files changed

+229
-45
lines changed

7 files changed

+229
-45
lines changed

include/mysql/plugin.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ typedef struct st_mysql_xid MYSQL_XID;
9090
Plugin API. Common for all plugin types.
9191
*/
9292

93-
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0108
93+
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0109
9494

9595
/*
9696
The allowable types of plugins
@@ -179,6 +179,12 @@ __MYSQL_DECLARE_PLUGIN(NAME, \
179179
#define PLUGIN_VAR_MEMALLOC 0x8000 /* String needs memory allocated */
180180
#define PLUGIN_VAR_NOPERSIST 0x10000 /* SET PERSIST_ONLY is prohibited
181181
for read only variables */
182+
/**
183+
There can be some variables which needs to be set before plugin is loaded but
184+
not after plugin is loaded. ex: GR specific variables. Below flag must be set
185+
for these kind of variables.
186+
*/
187+
#define PLUGIN_VAR_PERSIST_AS_READ_ONLY 0x20000
182188

183189
struct st_mysql_sys_var;
184190
struct st_mysql_value;
@@ -232,7 +238,8 @@ typedef void (*mysql_var_update_func)(MYSQL_THD thd,
232238
(PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR | \
233239
PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_NOCMDARG | \
234240
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC | \
235-
PLUGIN_VAR_NODEFAULT | PLUGIN_VAR_NOPERSIST)
241+
PLUGIN_VAR_NODEFAULT | PLUGIN_VAR_NOPERSIST | \
242+
PLUGIN_VAR_PERSIST_AS_READ_ONLY)
236243

237244
#define MYSQL_PLUGIN_VAR_HEADER \
238245
int flags; \

rapid/plugin/group_replication/src/plugin.cc

+60-42
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
include/group_replication.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 server1]
6+
7+
############################################################
8+
# 1. Persist configuration on server1.
9+
[connection server1]
10+
SET PERSIST group_replication_group_name= "GROUP_REPLICATION_GROUP_NAME";
11+
SET PERSIST group_replication_group_seeds= @@GLOBAL.group_replication_group_seeds;
12+
SET PERSIST group_replication_local_address= @@GLOBAL.group_replication_local_address;
13+
SET PERSIST group_replication_start_on_boot= ON;
14+
SET PERSIST group_replication_bootstrap_group= ON;
15+
16+
############################################################
17+
# 2. Restart server1, it must bootstrap the group.
18+
# restart
19+
include/rpl_reconnect.inc
20+
include/gr_wait_for_member_state.inc
21+
SELECT variable_name, variable_source FROM performance_schema.variables_info WHERE variable_source IN ('PERSISTED');
22+
variable_name variable_source
23+
group_replication_bootstrap_group PERSISTED
24+
group_replication_group_name PERSISTED
25+
group_replication_group_seeds PERSISTED
26+
group_replication_local_address PERSISTED
27+
group_replication_start_on_boot PERSISTED
28+
29+
############################################################
30+
# 3. Persist configuration on server2.
31+
[connection server2]
32+
SET PERSIST group_replication_group_name= "GROUP_REPLICATION_GROUP_NAME";
33+
SET PERSIST group_replication_group_seeds= @@GLOBAL.group_replication_group_seeds;
34+
SET PERSIST group_replication_local_address= @@GLOBAL.group_replication_local_address;
35+
SET PERSIST group_replication_start_on_boot= ON;
36+
37+
############################################################
38+
# 4. Restart server2, it must join the group.
39+
# restart
40+
include/rpl_reconnect.inc
41+
include/gr_wait_for_member_state.inc
42+
include/rpl_gr_wait_for_number_of_members.inc
43+
SELECT variable_name, variable_source FROM performance_schema.variables_info WHERE variable_source IN ('PERSISTED');
44+
variable_name variable_source
45+
group_replication_group_name PERSISTED
46+
group_replication_group_seeds PERSISTED
47+
group_replication_local_address PERSISTED
48+
group_replication_start_on_boot PERSISTED
49+
50+
############################################################
51+
# 5. Clean up.
52+
[connection server1]
53+
RESET PERSIST;
54+
SET GLOBAL group_replication_start_on_boot= OFF;
55+
[connection server2]
56+
RESET PERSIST;
57+
SET GLOBAL group_replication_start_on_boot= OFF;
58+
include/group_replication_end.inc
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
################################################################################
2+
# This test is to test if group replication can be started with needed variables
3+
# persisted into mysqld-auto.cnf file.
4+
# Test:
5+
# 1. Persist configuration on server1.
6+
# 2. Restart server1, it must bootstrap the group.
7+
# 3. Persist configuration on server2.
8+
# 4. Restart server2, it must join the group.
9+
# 5. Clean up.
10+
################################################################################
11+
--source include/big_test.inc
12+
--source ../inc/have_group_replication_plugin.inc
13+
--let $rpl_skip_group_replication_start= 1
14+
--source ../inc/group_replication.inc
15+
16+
17+
--echo
18+
--echo ############################################################
19+
--echo # 1. Persist configuration on server1.
20+
--let $rpl_connection_name= server1
21+
--source include/rpl_connection.inc
22+
--replace_result $group_replication_group_name GROUP_REPLICATION_GROUP_NAME
23+
--eval SET PERSIST group_replication_group_name= "$group_replication_group_name"
24+
--eval SET PERSIST group_replication_group_seeds= @@GLOBAL.group_replication_group_seeds
25+
--eval SET PERSIST group_replication_local_address= @@GLOBAL.group_replication_local_address
26+
SET PERSIST group_replication_start_on_boot= ON;
27+
SET PERSIST group_replication_bootstrap_group= ON;
28+
29+
30+
--echo
31+
--echo ############################################################
32+
--echo # 2. Restart server1, it must bootstrap the group.
33+
--let $allow_rpl_inited= 1
34+
--source include/restart_mysqld.inc
35+
--let $rpl_server_number= 1
36+
--source include/rpl_reconnect.inc
37+
38+
--let $group_replication_member_state= ONLINE
39+
--source ../inc/gr_wait_for_member_state.inc
40+
41+
SELECT variable_name, variable_source FROM performance_schema.variables_info WHERE variable_source IN ('PERSISTED');
42+
43+
44+
--echo
45+
--echo ############################################################
46+
--echo # 3. Persist configuration on server2.
47+
--let $rpl_connection_name= server2
48+
--source include/rpl_connection.inc
49+
--replace_result $group_replication_group_name GROUP_REPLICATION_GROUP_NAME
50+
--eval SET PERSIST group_replication_group_name= "$group_replication_group_name"
51+
--eval SET PERSIST group_replication_group_seeds= @@GLOBAL.group_replication_group_seeds
52+
--eval SET PERSIST group_replication_local_address= @@GLOBAL.group_replication_local_address
53+
SET PERSIST group_replication_start_on_boot= ON;
54+
55+
56+
--echo
57+
--echo ############################################################
58+
--echo # 4. Restart server2, it must join the group.
59+
--let $allow_rpl_inited= 1
60+
--source include/restart_mysqld.inc
61+
--let $rpl_server_number= 2
62+
--source include/rpl_reconnect.inc
63+
64+
--let $group_replication_member_state= ONLINE
65+
--source ../inc/gr_wait_for_member_state.inc
66+
67+
--let $group_replication_number_of_members= 2
68+
--source ../inc/gr_wait_for_number_of_members.inc
69+
70+
SELECT variable_name, variable_source FROM performance_schema.variables_info WHERE variable_source IN ('PERSISTED');
71+
72+
73+
--echo
74+
--echo ############################################################
75+
--echo # 5. Clean up.
76+
--let $rpl_connection_name= server1
77+
--source include/rpl_connection.inc
78+
RESET PERSIST;
79+
SET GLOBAL group_replication_start_on_boot= OFF;
80+
81+
--let $rpl_connection_name= server2
82+
--source include/rpl_connection.inc
83+
RESET PERSIST;
84+
SET GLOBAL group_replication_start_on_boot= OFF;
85+
86+
--source ../inc/group_replication_end.inc

sql/persisted_variable.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ void Persisted_variables_cache::set_variable(THD *thd, set_var *setvar)
256256
/* modification to in-memory must be thread safe */
257257
mysql_mutex_lock(&m_LOCK_persist_variables);
258258
/* if present update variable with new value else insert into hash */
259-
if (setvar->type == OPT_PERSIST_ONLY && setvar->var->is_readonly())
259+
if ((setvar->type == OPT_PERSIST_ONLY && setvar->var->is_readonly()) ||
260+
setvar->var->is_plugin_var_read_only())
260261
m_persist_ro_variables[tmp_var.key]= tmp_var.value;
261262
else
262263
{

sql/set_var.h

+5
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ class sys_var
194194
timestamp = 0;
195195
}
196196
virtual bool is_non_persistent() {return flags & NOTPERSIST; }
197+
/**
198+
Check if plugin variable is persisted as a read only variable. For
199+
server variables always return false.
200+
*/
201+
virtual bool is_plugin_var_read_only() { return 0; }
197202

198203
/**
199204
Update the system variable with the default value from either

sql/sql_plugin_var.h

+9
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,15 @@ class sys_var_pluginvar: public sys_var
277277
{ return (plugin_var->flags & PLUGIN_VAR_NOPERSIST); }
278278
void set_is_plugin(bool val)
279279
{ is_plugin= val; }
280+
/**
281+
Check if plugin variable is persisted as a read only variable.
282+
283+
@return
284+
@retval true
285+
@retval false
286+
*/
287+
bool is_plugin_var_read_only()
288+
{ return (plugin_var->flags & PLUGIN_VAR_PERSIST_AS_READ_ONLY); }
280289
};
281290

282291
/*

0 commit comments

Comments
 (0)