Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit 59fa4e4

Browse files
committed
Bug#31968366 SET PERSIST FOR COMPONENTS GENERATES A FLOOD OF WARNINGS
Description: ----------- Persisting component-defined system variables causes a flood of "Currently unknown variable" messages when the component is installed and registering its system variables. This also results in repeated and unnecessary invocations of the check() and update() callback functions for each system variable, persisted or otherwise. Analysis: --------- While registering component system variable it will add the variable into system_variable_hash and then in Persisted_variables_cache::set_persist_options() the persisted variables will be find in system_variable_hash if not found, then it will be stored in m_persist_plugin_variables. In the current case while loading the validate password component we have validate_password.check_user_name which is 5th variable while loading the component. So while registering first variable validate_password.check_user_name will not be found in system_variable_hash, and hence that variable is stored in m_persist_plugin_variables and the storing happens for multiple times because m_persist_plugin_variables is a vector type. Fix: ---- changed m_persist_plugin_variables type to unordered_set from vector type, so that variables duplication will not be allowed. RB#26373
1 parent a4698d4 commit 59fa4e4

6 files changed

Lines changed: 82 additions & 36 deletions

‎mysql-test/r/persisted_variables_for_component.result‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ validate_password.policy STRONG
4949
SET PERSIST validate_password.length= 13;
5050
SELECT * FROM performance_schema.persisted_variables;
5151
VARIABLE_NAME VARIABLE_VALUE
52-
validate_password.policy STRONG
5352
validate_password.length 13
53+
validate_password.policy STRONG
5454
RESET PERSIST `validate_password.length`;
5555
SELECT * FROM performance_schema.persisted_variables;
5656
VARIABLE_NAME VARIABLE_VALUE
@@ -64,3 +64,23 @@ validate_password.policy STRONG
6464
RESET PERSIST;
6565
SELECT * FROM performance_schema.persisted_variables;
6666
VARIABLE_NAME VARIABLE_VALUE
67+
#
68+
# BUG#31968366: SET PERSIST FOR COMPONENTS GENERATES A FLOOD OF WARNINGS
69+
#
70+
INSTALL COMPONENT 'file://component_validate_password';
71+
SET @@persist.validate_password.length=10;
72+
SET @@persist.validate_password.check_user_name=OFF;
73+
SELECT * FROM performance_schema.persisted_variables;
74+
VARIABLE_NAME VARIABLE_VALUE
75+
validate_password.check_user_name OFF
76+
validate_password.length 10
77+
UNINSTALL COMPONENT 'file://component_validate_password';
78+
INSTALL COMPONENT 'file://component_validate_password';
79+
SELECT COUNT(*) FROM performance_schema.error_log WHERE ERROR_CODE = "MY-013185";
80+
COUNT(*)
81+
0
82+
UNINSTALL COMPONENT 'file://component_validate_password';
83+
# Test RESET PERSIST after component is uninstalled
84+
RESET PERSIST;
85+
SELECT * FROM performance_schema.persisted_variables;
86+
VARIABLE_NAME VARIABLE_VALUE

‎mysql-test/r/read_only_persisted_plugin_variables.result‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ CALL mtr.add_suppression("Plugin audit_log reported *");
118118
# Both queries must return 101 rows.
119119
SELECT * FROM performance_schema.persisted_variables;
120120
VARIABLE_NAME VARIABLE_VALUE
121+
replica_type_conversions
121122
innodb_log_buffer_size 16777216
122123
slave_type_conversions
123-
replica_type_conversions
124124
back_log 80
125125
binlog_gtid_simple_recovery ON
126126
disabled_storage_engines

‎mysql-test/t/persisted_variables_for_component.test‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,22 @@ RESET PERSIST;
9090
# return 0 rows
9191
SELECT * FROM performance_schema.persisted_variables;
9292

93+
94+
--echo #
95+
--echo # BUG#31968366: SET PERSIST FOR COMPONENTS GENERATES A FLOOD OF WARNINGS
96+
--echo #
97+
98+
INSTALL COMPONENT 'file://component_validate_password';
99+
SET @@persist.validate_password.length=10;
100+
SET @@persist.validate_password.check_user_name=OFF;
101+
# return 2 rows
102+
SELECT * FROM performance_schema.persisted_variables;
103+
UNINSTALL COMPONENT 'file://component_validate_password';
104+
INSTALL COMPONENT 'file://component_validate_password';
105+
# with fix should return 0 rows, without fix it will return 63 rows
106+
SELECT COUNT(*) FROM performance_schema.error_log WHERE ERROR_CODE = "MY-013185";
107+
UNINSTALL COMPONENT 'file://component_validate_password';
108+
--echo # Test RESET PERSIST after component is uninstalled
109+
RESET PERSIST;
110+
# return 0 rows
111+
SELECT * FROM performance_schema.persisted_variables;

‎sql/persisted_variable.cc‎

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -395,24 +395,15 @@ bool Persisted_variables_cache::set_variable(THD *thd, set_var *setvar) {
395395
m_persist_ro_variables[tmp_var.key] = tmp_var;
396396
else {
397397
/*
398-
if element is present remove from current position and insert
399-
at end of vector to restore insertion order.
398+
if element is present remove it and insert
399+
it again with new value.
400400
*/
401-
string str = tmp_var.key;
402-
auto itt =
403-
std::find_if(m_persist_variables.begin(), m_persist_variables.end(),
404-
[str](st_persist_var const &s) { return s.key == str; });
405-
if (itt != m_persist_variables.end()) m_persist_variables.erase(itt);
406-
m_persist_variables.push_back(tmp_var);
401+
m_persist_variables.erase(tmp_var);
402+
m_persist_variables.insert(tmp_var);
407403
/* for plugin variables update m_persist_plugin_variables */
408404
if (setvar->var->cast_pluginvar()) {
409-
auto it = std::find_if(
410-
m_persist_plugin_variables.begin(),
411-
m_persist_plugin_variables.end(),
412-
[str](st_persist_var const &s) { return s.key == str; });
413-
if (it != m_persist_plugin_variables.end())
414-
m_persist_plugin_variables.erase(it);
415-
m_persist_plugin_variables.push_back(tmp_var);
405+
m_persist_plugin_variables.erase(tmp_var);
406+
m_persist_plugin_variables.insert(tmp_var);
416407
}
417408
}
418409
unlock();
@@ -698,7 +689,8 @@ bool Persisted_variables_cache::set_persist_options(bool plugin_options) {
698689
THD *thd;
699690
LEX lex_tmp, *sav_lex = nullptr;
700691
List<set_var_base> tmp_var_list;
701-
vector<st_persist_var> *persist_variables = nullptr;
692+
std::unordered_set<st_persist_var, st_persist_var_hash> *persist_variables =
693+
nullptr;
702694
bool result = false, new_thd = false;
703695
const std::vector<std::string> priv_list = {
704696
"ENCRYPTION_KEY_ADMIN", "ROLE_ADMIN", "SYSTEM_VARIABLES_ADMIN",
@@ -779,9 +771,10 @@ bool Persisted_variables_cache::set_persist_options(bool plugin_options) {
779771
keep track of this variable so that it is set when plugin
780772
is loaded and continue with remaining persisted variables
781773
*/
782-
m_persist_plugin_variables.push_back(*iter);
783-
LogErr(WARNING_LEVEL, ER_UNKNOWN_VARIABLE_IN_PERSISTED_CONFIG_FILE,
784-
var_name.c_str());
774+
auto ret = m_persist_plugin_variables.insert(*iter);
775+
if (ret.second == true)
776+
LogErr(WARNING_LEVEL, ER_UNKNOWN_VARIABLE_IN_PERSISTED_CONFIG_FILE,
777+
var_name.c_str());
785778
continue;
786779
}
787780
/*
@@ -867,9 +860,7 @@ bool Persisted_variables_cache::set_persist_options(bool plugin_options) {
867860
Once persisted variables are SET in the server,
868861
update variables source/user/timestamp/host from m_persist_variables.
869862
*/
870-
auto it = std::find_if(
871-
m_persist_variables.begin(), m_persist_variables.end(),
872-
[var_name](st_persist_var const &s) { return s.key == var_name; });
863+
auto it = m_persist_variables.find(*iter);
873864
if (it != m_persist_variables.end()) {
874865
/* persisted variable is found */
875866
sysvar->set_source(enum_variable_source::PERSISTED);
@@ -1047,7 +1038,7 @@ bool Persisted_variables_cache::extract_variables_from_json(const Json_dom *dom,
10471038
if (is_read_only)
10481039
m_persist_ro_variables[var_name] = persist_var;
10491040
else
1050-
m_persist_variables.push_back(persist_var);
1041+
m_persist_variables.insert(persist_var);
10511042
unlock();
10521043
}
10531044
return false;
@@ -1092,14 +1083,12 @@ void Persisted_variables_cache::load_aliases() {
10921083
}
10931084
};
10941085
lock();
1095-
size_t size = m_persist_variables.size();
1096-
for (size_t i = 0; i < size; i++) {
1097-
auto var = m_persist_variables[i];
1086+
for (auto iter : m_persist_variables) {
10981087
insert_alias(
10991088
[&](const char *name) -> bool {
11001089
return var_set.find(name) != var_set.end();
11011090
},
1102-
[&](st_persist_var &v) { m_persist_variables.push_back(v); }, var);
1091+
[&](st_persist_var &v) { m_persist_variables.insert(v); }, iter);
11031092
}
11041093
for (auto pair : m_persist_ro_variables) {
11051094
insert_alias(
@@ -1375,7 +1364,8 @@ bool Persisted_variables_cache::reset_persisted_variables(THD *thd,
13751364
/**
13761365
Return in-memory copy persist_variables_
13771366
*/
1378-
vector<st_persist_var> *Persisted_variables_cache::get_persisted_variables() {
1367+
std::unordered_set<st_persist_var, st_persist_var_hash>
1368+
*Persisted_variables_cache::get_persisted_variables() {
13791369
return &m_persist_variables;
13801370
}
13811371

‎sql/persisted_variable.h‎

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include <stddef.h>
2727
#include <map>
2828
#include <string>
29-
#include <vector>
29+
#include <unordered_set>
3030

3131
#include "my_alloc.h"
3232
#include "my_inttypes.h"
@@ -60,6 +60,21 @@ struct st_persist_var {
6060
st_persist_var(const std::string key, const std::string value,
6161
const ulonglong timestamp, const std::string user,
6262
const std::string host, const bool is_null);
63+
/* This is custom comparision function used to make the unordered_set
64+
to work with the default std::hash for userdefined types. */
65+
bool operator==(const st_persist_var &persist_var) const {
66+
return key == persist_var.key;
67+
}
68+
};
69+
70+
/**
71+
STRUCT st_persist_var_hash
72+
73+
This structure has a custom hasher function used to make the unordered_set
74+
to work with the default std::hash for userdefined types.
75+
*/
76+
struct st_persist_var_hash {
77+
size_t operator()(const st_persist_var &pv) const { return pv.key.length(); }
6378
};
6479

6580
/**
@@ -71,7 +86,7 @@ struct st_persist_var {
7186
--------
7287
When first SET PERSIST statement is executed we instantiate
7388
Persisted_variables_cache which loads the config file if present into
74-
m_persist_variables vector. This is a singleton operation. m_persist_variables
89+
m_persist_variables set. This is a singleton operation. m_persist_variables
7590
is an in-memory copy of config file itself. If the SET statement passes then
7691
this in-memory is updated and flushed to file as an atomic operation.
7792
@@ -114,7 +129,8 @@ class Persisted_variables_cache {
114129
/**
115130
Get persisted variables
116131
*/
117-
std::vector<st_persist_var> *get_persisted_variables();
132+
std::unordered_set<st_persist_var, st_persist_var_hash>
133+
*get_persisted_variables();
118134
/**
119135
Get persisted static variables
120136
*/
@@ -174,9 +190,10 @@ class Persisted_variables_cache {
174190

175191
private:
176192
/* In memory copy of persistent config file */
177-
std::vector<st_persist_var> m_persist_variables;
193+
std::unordered_set<st_persist_var, st_persist_var_hash> m_persist_variables;
178194
/* copy of plugin variables whose plugin is not yet installed */
179-
std::vector<st_persist_var> m_persist_plugin_variables;
195+
std::unordered_set<st_persist_var, st_persist_var_hash>
196+
m_persist_plugin_variables;
180197
/* In memory copy of read only persistent variables */
181198
std::map<std::string, st_persist_var> m_persist_ro_variables;
182199

‎storage/perfschema/pfs_variable.cc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ int PFS_system_persisted_variables_cache::do_materialize_all(THD *unsafe_thd) {
490490
if ((m_safe_thd = get_THD(unsafe_thd)) != nullptr) {
491491
Persisted_variables_cache *pv = Persisted_variables_cache::get_instance();
492492
if (pv) {
493-
vector<st_persist_var> *persist_variables = pv->get_persisted_variables();
493+
auto *persist_variables = pv->get_persisted_variables();
494494
pv->lock();
495495
for (auto iter = persist_variables->begin();
496496
iter != persist_variables->end(); iter++) {

0 commit comments

Comments
 (0)