Skip to content

Commit 2d3e2eb

Browse files
committed
WL#16938 Startup option server_memory
Description: The MySQL Server auto-tunes the default values of certain configuration parameters based on the total physical memory available to the server. This information may come from the cgroup configuration or from the system hardware configuration. This worklog allows the user to configure the amount of memory considered by the server when determining the default values. It adds a system variable called server_memory as a read_only non_persistent variable with a default value of 0 indiciating no limits set. In case the server is configured to use more memory than what the server can access, the server throws an error during bootstrap and halts. Note: If the value is not provided, server_memory will default to 0. When the value is 0 (either default or manually set to 0), the server will fallback to available physical memory using cgroup or hardware as implemented in WL#16484. Change-Id: I39310955d952fef2b65a767c74481660daef4f2c
1 parent 79f82bb commit 2d3e2eb

File tree

11 files changed

+211
-1
lines changed

11 files changed

+211
-1
lines changed

components/library_mysys/my_system.cc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,17 @@
4848
#include <unistd.h>
4949
#endif
5050

51-
uint64_t my_physical_memory() noexcept {
51+
namespace {
52+
ulonglong configured_memory{0};
53+
} // anonymous namespace
54+
55+
/**
56+
Get the total physical memory accessible to the server. Tries to read cgroup
57+
limits first. If failed or no limits were found, then tries to read from the
58+
system using corresponding system APIs.
59+
@return total physical memory available to the server, or 0 on failure
60+
*/
61+
static inline uint64_t total_physical_memory() noexcept {
5262
try {
5363
uint64_t mem = 0;
5464
#ifdef _WIN32
@@ -77,6 +87,26 @@ uint64_t my_physical_memory() noexcept {
7787
}
7888
}
7989

90+
bool init_my_physical_memory(ulonglong memory) {
91+
if (memory == 0) {
92+
/* No limit. Physical memory available should be returned */
93+
return true;
94+
}
95+
if (memory <= total_physical_memory()) {
96+
configured_memory = memory;
97+
return true;
98+
}
99+
100+
return false;
101+
}
102+
103+
uint64_t my_physical_memory() noexcept {
104+
if (configured_memory != 0) {
105+
return configured_memory;
106+
}
107+
return total_physical_memory();
108+
}
109+
80110
uint32_t my_num_vcpus() noexcept {
81111
try {
82112
uint32_t n_vcpus = 0;

include/mysql/components/library_mysys/my_system.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@
2525

2626
#include <cstdint>
2727

28+
using ulonglong = unsigned long long;
29+
30+
/**
31+
Initialize the my_physical_memory function using server_memory option
32+
@param[in] memory Value of the server_memory startup option
33+
34+
@note The input value of 0 indicates no limits, and underlying container/host
35+
configuration must be used
36+
@return true on success, false if input memory value is invalid
37+
*/
38+
bool init_my_physical_memory(ulonglong memory);
39+
2840
/**
2941
Determine the total physical memory available in bytes.
3042

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,9 @@ The following options may be given as the first argument:
13281328
--server-id=# Uniquely identifies the server instance in the community
13291329
of replication partners
13301330
--server-id-bits=# Set number of significant bits in server-id
1331+
--server-memory=# Memory (in bytes) used by the MySQL Server when
1332+
auto-tuning the default values of the configuration
1333+
parameters which depend on memory
13311334
--session-track-gtids=name
13321335
Controls the amount of global transaction ids to be
13331336
included in the response packet sent by the
@@ -1960,6 +1963,7 @@ select-into-disk-sync FALSE
19601963
select-into-disk-sync-delay 0
19611964
server-id 1
19621965
server-id-bits 32
1966+
server-memory 0
19631967
session-track-gtids OFF
19641968
session-track-schema TRUE
19651969
session-track-state-change FALSE

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,9 @@ The following options may be given as the first argument:
13311331
--server-id=# Uniquely identifies the server instance in the community
13321332
of replication partners
13331333
--server-id-bits=# Set number of significant bits in server-id
1334+
--server-memory=# Memory (in bytes) used by the MySQL Server when
1335+
auto-tuning the default values of the configuration
1336+
parameters which depend on memory
13341337
--session-track-gtids=name
13351338
Controls the amount of global transaction ids to be
13361339
included in the response packet sent by the
@@ -1972,6 +1975,7 @@ select-into-disk-sync FALSE
19721975
select-into-disk-sync-delay 0
19731976
server-id 1
19741977
server-id-bits 32
1978+
server-memory 0
19751979
session-track-gtids OFF
19761980
session-track-schema TRUE
19771981
session-track-state-change FALSE
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
select @@global.server_memory;
2+
@@global.server_memory
3+
0
4+
select @@session.server_memory;
5+
ERROR HY000: Variable 'server_memory' is a GLOBAL variable
6+
show global variables like 'server_memory';
7+
Variable_name Value
8+
server_memory 0
9+
show session variables like 'server_memory';
10+
Variable_name Value
11+
server_memory 0
12+
select * from performance_schema.global_variables where variable_name='server_memory';
13+
VARIABLE_NAME VARIABLE_VALUE
14+
server_memory 0
15+
select * from performance_schema.session_variables where variable_name='server_memory';
16+
VARIABLE_NAME VARIABLE_VALUE
17+
server_memory 0
18+
set global server_memory=1G;
19+
ERROR HY000: Variable 'server_memory' is a read only variable
20+
set session server_memory=1G;
21+
ERROR HY000: Variable 'server_memory' is a read only variable
22+
set persist server_memory=1G;
23+
ERROR HY000: Variable 'server_memory' is a read only variable
24+
set persist_only server_memory=1G;
25+
ERROR HY000: Variable 'server_memory' is a non persistent read only variable
26+
# restart: --server-memory=512M
27+
select @@server_memory;
28+
@@server_memory
29+
536870912
30+
select * from performance_schema.global_variables where variable_name='server_memory';
31+
VARIABLE_NAME VARIABLE_VALUE
32+
server_memory 536870912
33+
select * from performance_schema.session_variables where variable_name='server_memory';
34+
VARIABLE_NAME VARIABLE_VALUE
35+
server_memory 536870912
36+
# restart: --server-memory=512M
37+
call mtr.add_suppression("Warning.* option 'server_memory': value -1 adjusted to 0.");
38+
select @@server_memory;
39+
@@server_memory
40+
536870912
41+
select * from performance_schema.global_variables where variable_name='server_memory';
42+
VARIABLE_NAME VARIABLE_VALUE
43+
server_memory 536870912
44+
select * from performance_schema.session_variables where variable_name='server_memory';
45+
VARIABLE_NAME VARIABLE_VALUE
46+
server_memory 536870912
47+
# Cleanup by restart
48+
# restart
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Variable server_memory indicates base memory value to be used by the server
2+
# when auto-tuning default values of configuration parameters
3+
# Note: Value of 0 implies no limits, read from cgroup/hardware
4+
# Note: Very small value implies, configurations defaults to minimum value
5+
6+
#
7+
# show that it's global
8+
#
9+
select @@global.server_memory;
10+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
11+
select @@session.server_memory;
12+
show global variables like 'server_memory';
13+
show session variables like 'server_memory';
14+
--disable_warnings
15+
select * from performance_schema.global_variables where variable_name='server_memory';
16+
select * from performance_schema.session_variables where variable_name='server_memory';
17+
--enable_warnings
18+
19+
#
20+
# show that it's read-only
21+
#
22+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
23+
set global server_memory=1G;
24+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
25+
set session server_memory=1G;
26+
27+
#
28+
# show that it's non persistent
29+
#
30+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
31+
set persist server_memory=1G;
32+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
33+
set persist_only server_memory=1G;
34+
35+
#
36+
# Set the option and verify that it is reflected
37+
#
38+
--let $restart_parameters=restart: --server-memory=512M
39+
--source include/restart_mysqld.inc
40+
41+
select @@server_memory;
42+
43+
--disable_warnings
44+
select * from performance_schema.global_variables where variable_name='server_memory';
45+
select * from performance_schema.session_variables where variable_name='server_memory';
46+
--enable_warnings
47+
48+
#
49+
# Value less than 0 is adjusted to 0
50+
#
51+
--let $restart_parameters=restart: --server-memory=512M
52+
--source include/restart_mysqld.inc
53+
call mtr.add_suppression("Warning.* option 'server_memory': value -1 adjusted to 0.");
54+
55+
select @@server_memory;
56+
57+
--disable_warnings
58+
select * from performance_schema.global_variables where variable_name='server_memory';
59+
select * from performance_schema.session_variables where variable_name='server_memory';
60+
--enable_warnings
61+
62+
--echo # Cleanup by restart
63+
--let $restart_parameters=
64+
--source include/restart_mysqld.inc
65+

share/messages_to_error_log.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13143,6 +13143,9 @@ ER_SERVER_STARTING_WITH_RESOURCE
1314313143
ER_INFO_AUTHENTICATION_OCI
1314413144
eng "authentication_oci plugin reported: %s."
1314513145

13146+
ER_SERVER_MEMORY_OPTION_INVALID
13147+
eng "MySQL Server configured to use %llu bytes but can only access %llu bytes."
13148+
1314613149
################################################################################
1314713150
# Error numbers 50000 to 51999 are reserved. Please do not use them for
1314813151
# other error messages.

sql/mysqld.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,7 @@ char *my_bind_addr_str;
11911191
char *my_admin_bind_addr_str;
11921192
uint mysqld_admin_port;
11931193
bool listen_admin_interface_in_separate_thread;
1194+
ulonglong server_memory;
11941195
static const char *default_collation_name;
11951196
const char *default_storage_engine;
11961197
const char *default_tmp_storage_engine;
@@ -6742,6 +6743,21 @@ int init_common_variables() {
67426743
#endif
67436744

67446745
if (get_options(&remaining_argc, &remaining_argv)) return 1;
6746+
6747+
/* Adjust memory to be used based on "server_memory" iff explicitly provided
6748+
*/
6749+
if (server_memory > 0) {
6750+
if (!init_my_physical_memory(server_memory)) {
6751+
LogErr(ERROR_LEVEL, ER_SERVER_MEMORY_OPTION_INVALID, server_memory,
6752+
my_physical_memory());
6753+
return 1;
6754+
}
6755+
6756+
/* temptable_max_ram default is set according physical memory, needs to be
6757+
updated based on "server_memory" now */
6758+
update_temptable_max_ram_default();
6759+
}
6760+
67456761
/*
67466762
The opt_bin_log can be false (binary log is disabled) only if
67476763
--skip-log-bin/--disable-log-bin is configured or while the

sql/mysqld.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ extern char *my_bind_addr_str;
280280
extern char *my_admin_bind_addr_str;
281281
extern uint mysqld_admin_port;
282282
extern bool listen_admin_interface_in_separate_thread;
283+
extern ulonglong server_memory;
283284
extern char glob_hostname[HOSTNAME_LENGTH + 1];
284285
extern char system_time_zone_dst_on[30], system_time_zone_dst_off[30];
285286
extern char *opt_init_file;

sql/sys_vars.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,13 @@ static Sys_var_bool Sys_use_separate_thread_for_admin(
11911191
READ_ONLY NON_PERSIST GLOBAL_VAR(listen_admin_interface_in_separate_thread),
11921192
CMD_LINE(OPT_ARG), DEFAULT(false));
11931193

1194+
static Sys_var_ulonglong Sys_server_memory(
1195+
"server_memory",
1196+
"Memory (in bytes) used by the MySQL Server when auto-tuning the default "
1197+
"values of the configuration parameters which depend on memory",
1198+
READ_ONLY NON_PERSIST GLOBAL_VAR(server_memory), CMD_LINE(REQUIRED_ARG),
1199+
VALID_RANGE(0, ULLONG_MAX), DEFAULT(0), BLOCK_SIZE(1));
1200+
11941201
static Sys_var_bool Sys_password_require_current(
11951202
"password_require_current",
11961203
"Current password is needed to be specified in order to change it",
@@ -5174,6 +5181,25 @@ static Sys_var_ulonglong Sys_temptable_max_ram(
51745181
1ULL << 30 /* 1 GiB */, 1ULL << 32 /* 4 GiB */)),
51755182
BLOCK_SIZE(1));
51765183

5184+
void update_temptable_max_ram_default() {
5185+
mysql_mutex_lock(&LOCK_global_system_variables);
5186+
5187+
assert(server_memory > 0);
5188+
5189+
/* Auto tune default value based on "server_memory" */
5190+
const ulonglong new_default =
5191+
std::clamp(ulonglong{3 * (my_physical_memory() / 100)},
5192+
1ULL << 30 /* 1 GiB */, 1ULL << 32 /* 4 GiB */);
5193+
Sys_temptable_max_ram.update_default(new_default);
5194+
5195+
/* If "temptable_max_ram" is not set explicitly, update the default value */
5196+
if (Sys_temptable_max_ram.get_source() == COMPILED) {
5197+
temptable_max_ram = new_default;
5198+
}
5199+
5200+
mysql_mutex_unlock(&LOCK_global_system_variables);
5201+
}
5202+
51775203
static Sys_var_ulonglong Sys_temptable_max_mmap(
51785204
"temptable_max_mmap",
51795205
"Maximum amount of memory (in bytes) the TempTable storage engine is "

0 commit comments

Comments
 (0)